将浮点值分配给双精度值

Posted

技术标签:

【中文标题】将浮点值分配给双精度值【英文标题】:Assigning floating value to a double value 【发布时间】:2014-02-19 09:19:26 【问题描述】:

我指的是this Oracle 文档。在尝试执行以下操作时,

 public static void main(String args[])

    float f = 1.1f;
    double df = 1.1f;

    System.out.println("f=" + f);
    System.out.println("df=" + df);

    f = 1.5f;
    df = 1.5f;
    System.out.println("f=" + f);
    System.out.println("df=" + df);
 

输出是

f  = 1.1
df = 1.100000023841858
f  = 1.5
df = 1.5

为什么第二行输出显示的是近似值。但不适用于第四行。 值是如何计算的?

【问题讨论】:

顺便说一句 1.1ffloat 文字,将其分配给 double 可能会产生误导。 第一个只是没有告诉你它具有相同的近似值floating-point-gui.de df 实际上是这个1.500000000000000,零被跳过了 有关浮点表示的更多信息,请参阅 ieee 754 标准 您的问题实际上是关于将单精度值打印作为双精度值。简而言之,Java 只打印足够的数字,以便准确地确定单精度或双精度值。当您将1.1f 打印为double 时,该类型具有更高的精度,因此需要更多的数字来明确double 的含义。见***.com/questions/916081/… 【参考方案1】:

不同之处在于1.5 可以精确地表示为双精度 - 而1.1 不能精确地表示。

这是因为周期性数字,任何(不可约)分数,其中分母具有在基数中不出现的质因数,需要在某个点之后周期性重复的无限数量的数字。例如,十进制的1/43/58/20 是有限的,因为2510 的质因数。但是1/3 不是有限的,2/31/75/6 也不是有限的,因为37 不是10 的因数。分母中以5 为质数的分数可以在基数10 中是有限的,但在基数2 中是有限的——这对于大多数浮点数新手用户来说是最大的困惑。

将无限多个实数压缩为有限位数 需要一个近似的表示。虽然有无限 许多整数,在大多数程序中整数计算的结果可以 以 32 位存储。相反,给定任何固定数量的比特, 大多数实数计算将产生的数量 不能用那么多位精确表示。因此 浮点计算的结果通常必须按顺序四舍五入 以适应其有限的表示。这个舍入误差是 浮点计算的特征。

查看here了解更多详情

【讨论】:

这个近似值是如何计算的? 但他两次都分配了 1.1f(不是 1.1)。不应该是同一个常数吗? @starmole 将1.1f 分配给double 会导致比可能的数字更不准确,即,当打印为双精度数字时,它是如此不准确,以至于它在打印时打印 000023.. 部分因为float 直接跳过打印该不准确之处,因为它知道打印数字超过某个点没有更多价值。如果您将 1.1 分配为 double,您将在数量级上更接近 1.1,因为您可以使用更多位。那将打印为“1.1”。 @starmole:Java 打印浮点的默认设置是打印足够的数字来唯一标识其类型中的值。在float 中,“1.1”就足够了,因为1.1f(正好是 1.10000002384185791015625)比任何其他float 更接近 1.1。在double,“1.1”是不够的,因为double 1.100000000000000088817841970012523233890533447265625更接近1.1比1.10000002384185791015625是,那么你需要更多的数字更贴近的1.10000002384185791015625值。 SPAN> 【参考方案2】:

示例

在处理小数位时考虑二进制,更重要的是考虑二进制。

4    2    1  .  1/2    1/4    1/8
0    0    1  .  1      0      0

因此,如您所见,计算机可以毫无问题地表示这一点。现在让我们看看1.1

4    2   1   .  1/2    1/4    1/8    1/16
0    0   1   .  0      0      0      1

目前,我们有1.0625。可以想象,要准确得到0.0475 有点困难,但我们可以继续尝试:

4    2   1   .  1/2    1/4    1/8    1/16    1/32     1/64     1/128
0    0   1   .  0      0      0      1       1        0        0

现在我们已经到了1.8,所以让我们继续吧..

4    2   1   .  1/2    1/4    1/8    1/16    1/32     1/64     1/128
0    0   1   .  0      0      0      1       1        1        0

我们必须0.915625..

4    2   1   .  1/2    1/4    1/8    1/16    1/32     1/64     1/128
0    0   1   .  0      0      0      1       1        1        1

我们在0.9234375

说明

我相信您可以看到我的目标。你想要表示的数字和二进制可以表示的数字之间总是会有误差。有时,您会很幸运,例如1.5,而二进制表示它没有问题。其他时候,您会遇到问题,例如 1.1,并且二进制文件会尽可能接近。

【讨论】:

【参考方案3】:

是的,我们知道,一个数字在 double 中的表示比在 float 中的相同。浮点数以 32 位表示,而双精度数以 64 位表示。因此,当将浮点数分配给双精度时,数字将从 32 位扩展到 64 位。然后以准确的方式表示不准确的数字。那么,你是不是更明白这一点了?

【讨论】:

以上是关于将浮点值分配给双精度值的主要内容,如果未能解决你的问题,请参考以下文章

单精度和双精度浮点值有啥不同? [复制]

如何将浮点值转换为具有精确精度的整数,例如 123.3443 到 1233443?

变体浮点到双精度值转换,舍入到小数点后 1 位 [重复]

在 PHP 中将十进制/双精度/浮点值与 PDO 绑定的最佳方法是啥?

Fortran 90 中是不是有更好的双精度赋值?

在 SQLite 中存储浮点值会更改 Room DB 中的小数精度