Java 将浮点值赋给双精度值

Java 将浮点值赋给双精度值,java,floating-point,double,Java,Floating Point,Double,我指的是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); Sys

我指的是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.5
可以用双精度表示,而
1.1
不能精确表示

这是因为周期性的数字,任何分母有素数因子的(不可约的)分数都需要无穷多的数字,在某一点之后周期性地重复。例如,在十进制
1/4
3/5
8/20
是有限的,因为
2
5
10
的主要因素。但是
1/3
不是有限的,
2/3
1/7
5/6
,因为
3
7
不是
10
的因素。分母中素数因子为
5
的分数在基数
10
中是有限的,但在基数
2
中则不是有限的,这是大多数浮点数字新手最容易混淆的地方

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

查看更多详细信息

示例

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

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
,二进制就越接近了。

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

BTW
1.1f
是一个
float
文本,将其指定为double可能会产生误导。第一个并没有告诉你它有相同的近似值
df
是这
1.500000000000000
实际上,关于浮点表示的更多信息,跳过了零,参考ieee 754标准,您的问题实际上是关于将单个精度值打印为双精度值。简而言之,Java只打印足够的数字,以便准确地确定单精度或双精度值。当您将
1.1f
打印为
double
时,该类型具有更高的精度,因此需要更多的数字来明确表示确切的
double
。看看这个近似值是如何计算的吧?但他两次都赋值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.1000000000000088817841970012523233890533447265625比1.10000002384185791015625更接近1.1,所以需要更多的数字来接近1.10000002384185791015625的值。