我对双精度有疑问。当float值传递给double时,我会得到一些不同的结果。例如,
float f= 54.23f;
double d1 = f;
System.out.println(d1);
输出为54.22999954223633。有人可以解释这种行为背后的原因。它是否是两次默认值为14位小数精度。
答案 0 :(得分:6)
float
和double
的打印方式相同,因为Java规范要求打印所需数量的数字,以便将值与相同类型的相邻可表示值区分开来(根据我的回答{{ 3}},并在定义中查看here以获得更高的精度。)
由于float
具有较少的位来表示值,因此值较少,因此它们间隔较大,并且您不需要那么多的数字来区分它们。将值放入double
并打印时,Java规则要求打印更多数字,以便将值与附近的double
值区分开来。 println
函数不知道该值最初来自float
,并且不包含适合double
的信息。
54.23f
正好是54.229999542236328125(十六进制,0x1.b1d70ap + 5)。正好低于此值的float
值为54.2299957275390625(0x1.b1d708p + 5)和54.23000335693359375(0x1.b1d70cp + 5)。正如您所看到的,打印“54.229999”会将值与54.229995 ......和54.23 ......区分开来。但是,double
正好在54.23f
之上且仅在{{1}}之上的值是54.22999954223632101957264239899814128875732421875和54.22999954223633523042735760100185871124267578125。要区分该值,您需要“54.22999954223633”。
答案 1 :(得分:0)
这是因为浮动隐藏了额外的小数,双重显示它们。双精度将非常精确地表示实际数字并显示更多数字。
试试这个:
的System.out.println(f.doubleValue()); (需要首先将其作为 Float )
正如您所看到的,信息就在那里,它只是四舍五入。 希望这有帮助
答案 2 :(得分:0)
这是由于Internal Representation 浮点数通常从左到右打包到计算机数据中作为符号位,指数字段和有效数字(尾数)。
这被称为Accuracy Problems 事实上,浮点数不能精确地表示所有实数,并且浮点运算不能精确地表示真正的算术运算,这会导致许多令人惊讶的情况。这与计算机通常代表数字的有限精度有关。
这不是问题。这是双重的工作方式。您不必处理它并关心它。双精度就足够了。想想,你的数字与预期结果之间的差异在小数点后的14位。
如果您需要任意精确度,请使用java.math.BigDecimal
类。
或者如果您仍想使用double。这样做:
double d = 5.5451521841;
NumberFormat nf = new DecimalFormat("##.###");
System.out.println(nf.format(d));
如有任何疑问,请通知我。
答案 3 :(得分:0)
实际上这只是关于不同的可视化表示或将float / double转换为String。我们来看看内部二进制表示法
float f = 0.23f;
double d = f;
System.out.println(Integer.toBinaryString(Float.floatToIntBits(f)));
System.out.println(Long.toBinaryString(Double.doubleToLongBits(d)));
输出
111110011010111000010100011111
11111111001101011100001010001111100000000000000000000000000000
表示f
已转换为d1
而没有任何失真,有效数字相同
答案 4 :(得分:-1)
double
和float
代表不同格式的数字。
因此,你必然会发现某些数字完全以一种格式存储而不能存储在另一种格式中。您碰巧找到了一个正确适合float
但不适合exactly
的`double。
当使用两种不同的格式化程序时,也会出现此问题。