fastjson处理double的精度问题

牧码人-blacksonny在路上      2022-02-08     141

关键词:

项目中使用 fastjson 来处理 json 格式,当前使用的版本为1.1.37。在和其它系统交互时,将一个json串传给了对方,原值为5.0,json 处理后格式为:{"dou", 5}; 结果对方处理该串报错了, 原因是他将串整理转成 Map ,在取值时强制转为了 Double ,因为拿到的值转化是 Integer 类型,强转肯定异常了。 简单的做法应该通过 Double.valueOf(value)  进行处理。但无奈合作方不愿意处理。 于是测试了下fastjson处理这个串时,通过以下做处理, 输出的结果为 {"dou", 5}。

JSONObject jsonObject = new JSONObject();
Double dou = new Double(5.0);
jsonObject.put("dou", dou);
System.out.println(JSON.toJSONString(jsonObject));

想要输出{"dou",5.0} 怎么办, 跟踪了下源码,发现在 DoubleSerializer 的 write 方法中,判断了结尾如果是.0 就截掉了。

doubleText = Double.toString(doubleValue);
if(doubleText.endsWith(".0")) {
    doubleText = doubleText.substring(0, doubleText.length() - 2);
}

那想要的格式怎么办,可以通过自定义 filter 方式实现,:

 ValueFilter filter = new ValueFilter() {
            @Override
            public Object process(Object object, String name, Object value) {
                if(value instanceof BigDecimal || value instanceof Double || value instanceof Float){
                    return new BigDecimal(value.toString());
                }
                return value;
            }
        };

String s  = JSON.toJSONString(jsonObject, filter, new SerializerFeature[0]);

以上可以完美解决。后来想有没有跟好的方法呢。 于是网上搜索了一下,大多数都是这种做法,并且有人认为这是一个bug,于是突然想有没有可能 wenshao 会处理一下,于是在 github 找到 fastjson 的最新版本 1.2.23。 先修改 pom 文件,然后运行。发现即使不处理也能输出了 {"dou",5.0} 。 于是 debug 进去原来对 DoubleSerializer 进行了重写,并在 write 方法中原来处理格式的地方修改为如下:

if (decimalFormat == null) {
    out.writeDouble(doubleValue, true);
} else {
    String doubleText = decimalFormat.format(doubleValue);
    out.write(doubleText);
}

//out SerializeWriter
String doubleText = Double.toString(doubleValue);
if (isEnabled(SerializerFeature.WriteNullNumberAsZero) && doubleText.endsWith(".0")) {
    doubleText = doubleText.substring(0, doubleText.length() - 2);
}

即,以上粉色代码调用 SerializeWriter 的writeDouble 方法, 看绿色部分。 同时判断了 SerializerFeature.WriteNullNumberAsZero 和 结尾是否为 .0

就是通过这个解决了 double 精度的正常输出。  在使用 1.2.23时如果想输出{"dou", 5}, 可以通过设置 SerializerFeature.WriteNullNumberAsZero 实现。

System.out.println(JSON.toJSONString(jsonObject, SerializerFeature.WriteNullNumberAsZero));

啰嗦了这么,希望通过升级版本解决同样遇到这样问题的小伙伴。

double类型的精度问题

...简单的期望题,已知概率p求期望显然期望为1/p但在精度处理上就有点麻烦了,题目要求答案以最简分数的形式输出,误差要小于1e-6但我一开始错误的使用了除法运算求1/p,再求(1/p*1e6)/1e6的最简分数很显然精度丢失这是一条大... 查看详情

javadouble数据类型运算问题

...值是否大于0,如果大于0我们会做一件事情,小于0我们又处理其他事情。这样的情况通过double计算出来的结果去和0比较大小,尤其是有小数点的时候,经常会因为精度丢失而导致程序处理流程出错。所以一般对double类型进行运... 查看详情

float和double区别

...存储在DOUBLE中,精度为18位,有八个字节。一般来说,CPU处理单精度浮点数的速度比处理双精度浮点数快,尽量使用单精度浮点数float  查看详情

ios数据解析精度丢失

...String时就会出现精度丢失,因此我们需要对这些数据进行处理。这里我们要用到系统自带的NSDecimalNumber来对数据进行处理,这里我们采用接收NSString的方式注意:处理精度相关问题是用double 查看详情

float和double的区别float和double5点区别

...精度浮点数的表示范围:-1.79E+308~-1.79E+308。5、在程序中处理速度不同,一般来说,CPU处理单精度浮点数的速度比处理双精度浮点数快,如果不声明,默认小数为double类型,所以如果要用float的话,必须进行强转。 查看详情

bigdecimal类处理高精度计算

BigDecimal类处理高精度计算?Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。一般情... 查看详情

uniginemesh顶点坐标转换精度问题

...,因为显卡绘制double型承受不起;在拿出顶点的数据进行处理的过程中,始终采用double型数据进行中间转换计算,直至计算出最终结果;将double型的计算结果截取赋值给float型的顶点,此种情况下,转换后的顶点精度符合预期。... 查看详情

浮点类型说明浮float,double有啥区别啊

...38双精度浮点的表示范围:-1.79E+308~+1.79E+308(4)在程序中处理速属度不同一般来说,CPU处理单精度浮点数的速度比处理双精度浮点数快 参考技术B精度double更高一些,而且你输入小数的话会被默认识别为float.精度要求高的时候用D... 查看详情

java数据类型-精度失真问题

...有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际应用中,需要对更大或者更小的数进行运算和处理。float和double只能用来做科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal。Bi... 查看详情

double转换long丢失精度

...string,然后再转成long,做一个中转。或者也可以自己去处理IEEE浮点数格式来转化。doubled=2.01;longf;charbuff[32];sprintf(buff,"%.0f",d*100.0);sscanf(buff,"%d",&f);printf("%d",f);参考技术A十进制数在保存到电脑以后可能会产... 查看详情

浮点类型说明浮float,double有啥区别啊

...字节数不同、有效数字位数不同、数值取值范围、在程中处理速度不同1、在内存中占有的字节数不同:单精度浮点数在机内存占4个字节,双精度浮点数在机内存占8个字节。2、有效数字位数不同:单精度浮点数有效数字8位,双... 查看详情

ios-json解析精度丢失处理(nsstring,double,float)

前几天在IOS开发时发现一个JSON解析奇葩问题,会出现一定概率的错误,如下://出现BUG的条件必须是两位数,且带两位小数,类型还必须是float//两位数:十位必须是7、8、9;个位数随意//两位小数:... 查看详情

float,double等精度丢失问题float,double内存表示

...:http://msdn.microsoft.com/zh-cn/c151dt3s.aspx为何浮点数可能丢失精度浮点十进制值通常没有完全相同的二进制表示形式。这是CPU所采用的浮点数据表示形式的副作用。为此,可能会经历一些精度丢失,并且一些浮点运算可能会产生意外... 查看详情

double与bigdecimal精度问题

转自:http://superivan.iteye.com/blog/963628  [1]精确的浮点运算: 在Java里面,有时候为了保证数值的准确性需要精确的数据,先提供一个例子就可以发现问题了: publicclassFloatNumberTester{publicstaticvoidmain(Stringargs[]){System.out.... 查看详情

如何在 ARM 处理器中使用 NEON 和 double 值计算点积

】如何在ARM处理器中使用NEON和double值计算点积【英文标题】:HowtocomputedotproductwithNEONanddoublevaluesinARMprocessor【发布时间】:2013-05-1608:19:36【问题描述】:我需要做很多向量计算。因此,我认为应该使用NEON似乎是明智的。问题是... 查看详情

float和double有啥区别?

...位有效数字。3、longdouble型不同的编译系统对longdouble型的处理方法不同,VisualC++6.0对longdouble型和double一样处理,分配8个字节。参 查看详情

std::to_string(double) 的精度

】std::to_string(double)的精度【英文标题】:Theprecisionofstd::to_string(double)【发布时间】:2013-01-2510:53:11【问题描述】:使用std::to_string()将双精度转换为字符串时,有什么方法可以设置结果的精度?【问题讨论】:另见***.com/a/16606128/... 查看详情

double精度问题

/***相传国际象棋是古印度舍罕王的宰相达依尔发明的。*舍罕王十分喜欢,决定让宰相自己选择赏赐。*这位宰相指着8×8共64格的棋盘说:陛下,请您赏给我一些麦子吧,*在棋盘的第一个格子放1粒,第2格放2粒,第3格放4粒,*以... 查看详情