Java:添加2个浮点数,结果为double
据我所知,双精度数字在内存中保留64位。浮点数保留32位 我尝试了以下方法:Java:添加2个浮点数,结果为double,java,floating-point,double,Java,Floating Point,Double,据我所知,双精度数字在内存中保留64位。浮点数保留32位 我尝试了以下方法: double result=0.1f+0.3f; System.out.println(result); 因此,它会打印0.4000000059604645。是来自下一个内存块的数据(前32位和后32位)? 是别的吗 这一行: double result=0.1f+0.3f; 首先将字符串“0.1”和“0.3”转换为float值,然后使用float的规则添加这两个float值,最后将结果转换为double以执行赋值
double result=0.1f+0.3f;
System.out.println(result);
因此,它会打印0.4000000059604645
。是来自下一个内存块的数据(前32位和后32位)?是别的吗 这一行:
double result=0.1f+0.3f;
首先将字符串“0.1”和“0.3”转换为float
值,然后使用float
的规则添加这两个float
值,最后将结果转换为double
以执行赋值。将浮点文本转换为float
值会引入舍入错误。(就像1/3在基数10中有无限重复扩展一样,1/10和3/10在基数2中有无限重复扩展,并且不能在float
或double
中精确表示)添加float
可能会引入更多的错误(双关语)。从float
到double
的扩展是精确的,但系统随后假设扩展的分辨率包含有意义的数据
如果希望使用double
的规则进行加法,则需要首先将至少一个操作数转换为double
,可以使用强制转换,也可以使用double
文字:
double result=0.1f+0.3d;
在上述情况下,0.3将转换为double
到fulldouble
精度;0.1将转换为浮点
,然后扩展为双精度
,从而产生双精度
值,其舍入误差大于0.1d
。大多数编译器都会在编译时执行此操作
使用Oracle的javac编译器编译此代码(版本1.7.0_11,默认设置):
生成如下开头的字节码(使用javap-c进行反汇编):
并产生以下输出:
dff=0.4000000059604645
dfd=0.4000000014901161
ddd=0.4
dff==dfd: false
dff==ddd: false
dfd==ddd: false
ddd==0.4: true
最后一行显示“true”,因为0.1d和0.3d的表示错误以及加法的舍入错误(如果有)恰好以与0.4d的表示错误完全匹配的方式组合在一起。如果您将0.3
更改为0.2
(并将10*ddd==4
更改为10*ddd==3
),情况就不会这么好了
通常,无论您使用的是浮点
还是双精度
,都会出现一些舍入误差,结果不太可能精确。对于扩展精度,您应该使用。如果您只需要外观整洁的输出,请使用格式说明符(例如,使用System.out.printf()
或String.format()
)
您还应该阅读。请参阅:0.4没有精确的基数2表示法。在最低的条件下,它是2/5,5不是2的任何幂的系数。实际的双位模式是0x3FD9999999A,相当于0.40000000000000002220446049250313080847263336181640625。最后一个“真”的意思是ddd的值是最接近小数点0.4的双精度。@PatriciaShanahan-捕捉得好。我不知道我在想什么。我重新表述了答案的那一部分。不过,有趣的是,10*(0.4d)==4(精确)。有时,一次计算的舍入误差会抵消上一次计算的舍入误差,从而得到精确的结果。这就是在10*(0.4d)计算中发生的情况。
ldc2_w #2 // double 0.4000000059604645d
dstore_1
ldc2_w #4 // double 0.4000000014901161d
dstore_3
ldc2_w #6 // double 0.4d
dstore 5
dff=0.4000000059604645
dfd=0.4000000014901161
ddd=0.4
dff==dfd: false
dff==ddd: false
dfd==ddd: false
ddd==0.4: true