以 double 形式传递浮点值时的双精度

问题描述 投票:0回答:5

我对双精度有疑问。当将浮点值传递给双精度时,我会得到一些不同的结果。例如

float f= 54.23f;
double d1 = f;
System.out.println(d1);

输出为 54.22999954223633。有人可以解释这种行为背后的原因吗?是不是像 double 默认小数点后 14 位精度一样。

java floating-point double
5个回答
8
投票

相同的值对于

float
double
的打印方式不同,因为 Java 规范要求根据需要打印尽可能多的数字,以将该值与相同类型中的相邻可表示值区分开(根据我的答案 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.23”(四舍五入到小数点后六位数字的结果,得到 54.230000,并删除尾随零)将将该值与 54.229995… 和 54.23… 区分开来。但是,
double
的值分别为 54.22999954223632101957264239899814128875732421875 和 54.2299995422363352304273576010018587112 4267578125。为了区分该值,您需要“54.22999954223633”。
    


0
投票

试试这个:

System.out.println(f.doubleValue()); (当然需要先将其设为

Float

如您所见,信息就在那里,只是四舍五入。 希望这有帮助


0
投票

54.23f

输出

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
没有任何变形,有效数字相同
    


-1
投票
d1

double
代表不同格式的数字。

因此,您一定会发现某些数字可以完美地以一种格式存储,但不能以另一种格式存储。您碰巧找到了一个可以正确适合

float

但不适合

float
的“双”。

使用两个不同的格式化程序时也会出现此问题。


-1
投票
内部代表

浮点数通常从左到右作为符号位、指数字段和有效数字(尾数)打包到计算机数据中。
这称为

准确性问题

浮点数不能精确地表示所有实数,并且浮点运算不能精确地表示真正的算术运算,这一事实导致了许多令人惊讶的情况。这与计算机通常表示数字的有限精度有关。
这不是问题。这就是 double 的工作原理。你不必处理它并关心它。 double 的精度就足够了。想一想,你的数字与预期结果之间的差异就在小数点后 14 位。


如果您需要任意好的精度,请使用

exactly

类。




或者如果您仍然想使用 double。这样做:

java.math.BigDecimal

如有任何疑问,请告诉我。

© www.soinside.com 2019 - 2024. All rights reserved.