将 1234567.1234 的双精度值转换为 java 中的浮点数

Converting double value of 1234567.1234 to float in java

我正在尝试将 java 中的双精度转换为浮点数。

Double d = 1234567.1234;
Float f = d.floatValue();

我看到f的值为

1234567.1

我不是要打印浮点字符串值。我只是想知道在将 double 转换为 float 时不丢失任何精度的最大位数是多少。我可以在 java 中显示超过 8 位有效数字吗?

编辑。
不,你不能用 Java 中的浮点数获​​得更精确的结果,因为浮点数只能包含 32 位(4 字节)。如果您想要更高的精度,请继续使用 Double。 This 也可能有帮助

float: 32 bits (4 bytes) 其中 23 bits 用于尾数(6 到 9 个十进制数字,平均约 7 个)。 8 位用于指数,因此浮点数可以使用这 8 位将小数点“移动”到右侧或左侧。这样做可以避免在尾数中存储大量零,如 0.0000003 (3 × 10-7) 或 3000000 (3 × 107)。有1位用作符号位。

double64 位(8 个字节)其中 52 位 用于尾数(15 到 17 位十进制数字,平均约 16)。 11 位用于指数,1 位用于符号位。

我相信你达到了这个限制是什么导致了这个问题。

如果你改变

Double d = 123456789.1234;
Float f = d.floatValue();

您会看到浮点值将为 1.23456792E8

float 的精度是 大约 7 位小数,但由于浮点数以二进制形式存储,所以这是一个近似值。

为了说明所讨论的浮点值的实际精度,试试这个:

double d = 1234567.1234;
float f = (float)d;
System.out.printf("%.9f%n", d);
System.out.printf("%.9f%n", Math.nextDown(f));
System.out.printf("%.9f%n", f);
System.out.printf("%.9f%n", Math.nextUp(f));

输出

1234567.123400000
1234567.000000000
1234567.125000000
1234567.250000000

如您所见,有效小数精度是大约此数字的小数点后一位,即8位数字,但如果您运行编号为9876543.9876的代码,你得到:

9876543.987600000
9876543.000000000
9876544.000000000
9876545.000000000

只有7位精度。

I just wonder what is the maximum number of digits not to lose any precision when converting double to float.

也许你没有意识到,N位精度的概念已经很模糊了。毫无疑问,你的意思是 "N digits precision in base 10"。但与人类不同的是,我们的计算机使用 Base 2。

不可能在不损失精度的情况下将每个数字从 X 基数转换为 Y 基数(保留的数字数量有限),例如1/3rd 的值 完全 在 Base 3 中可以准确表示为“0.1”。在 Base 10 中,它有无限多的数字 0.3333333333333... 同样,在 Base 10 中通常可以完美表示数字,例如0.1 需要用基数 2 表示无限数量的数字。另一方面,0.5(基数 10)可以准确地表示为 0.1(基数 2)。

所以回到

I just wonder what is the maximum number of digits not to lose any precision when converting double to float.

答案是"it depends on the value"。通常引用的经验法则 "float has about 6 to 7 digits decimal precision" 只是一个近似值。它可能会更多或更少,具体取决于值。

处理浮点数时,相对精度的概念更有用,别想"digits",用相对误差代替。任何数字 N(在范围内)都可以用(最多)N/精度的误差表示,精度是所选格式中的尾数位数(例如,浮点数为 23 (+1),浮点数为 52 (+1)双倍的)。因此,表示为浮点数的十进制数的最大近似误差为 N / pow(2, 24)。误差可能更小,甚至为零,但永远不会更大。

23+1 源自这样一种约定,即浮点数按照所选的指数进行组织,使得第一个尾数位始终为 1(只要可能),因此不需要显式存储。物理存储的位数,例如因此,23 允许多一位的准确性。 (有一个例外情况,"whenever possible" 不适用,但在这里忽略它)。

TL;DR: floatordouble.

没有固定小数位数精度

这是一个简单的例子,支持没有安全的小数位数的观点。

考虑 0.1。

最接近的 IEEE 754 64 位二进制浮点数的精确值为 0.1000000000000000055511151231257827021181583404541015625。它转换为 32 位二进制浮点数为 0.100000001490116119384765625,与 0.1 相差甚远。

即使是单个有效数字和单个小数位,也可能会丢失精度。

除非你真的需要 float 的紧凑性,并且对精度要求很宽松,否则通常坚持使用 double 会更好。