是否有可能一个完全表示为float的数字不能完全表示为double?

Ank*_*kit 3 java floating-point double

我有一个问题是由另一个关于浮点数精度的问题引起的.

现在,我知道浮点数不能总是准确地表示,因此它们被存储为可以表示的最接近的浮点数.

我的问题实际上是关于float和和的表示的差异double.

这个问题来自哪里?

假设我这样做:

System.out.println(.475d+.075d);
Run Code Online (Sandbox Code Playgroud)

那么输出不会是0.55,但0.549999(我的机器上)

但是,当我这样做时:

System.out.println(.475f+.075f);
Run Code Online (Sandbox Code Playgroud)

我得到了正确的答案,即0.55(对我来说有点意外)

到目前为止,我的印象是double更精确(双倍会更精确到更长的小数位数)float.因此,如果无法精确表示double,则其等效浮点表示也将不准确地存储.

然而,我得到的结果对我来说有点令人不安.我很困惑,如果:

  1. 我对什么precision意思的理解不正确?
  2. float并且double表示不同,除了double有更多位?

Pio*_*sen 8

可以作为a float重新编号的数字也可以表示为double.

你读的只是格式化输出,你不读实际的二进制表示.

System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(.475d + .075d)));
// 11111111100001100110011001100110011001100110011001100110011001
System.out.println(Integer.toBinaryString(Float.floatToRawIntBits(.475f + .075f)));
// 111111000011001100110011001101

double d = .475d + .075d;
System.out.println(d);
// 0.5499999999999999
System.out.println((float)d);
// 0.55 (as expected)
System.out.println((double)(float)d);
// 0.550000011920929

System.out.println( .475f + .075f == 0.550000011920929d);
// true
Run Code Online (Sandbox Code Playgroud)


Jim*_*son 5

精度只意味着更多的位.不能表示为a的数字float 可以具有精确表示为a double,但是这些情况的数量相对于可能情况的总数无限小.

对于简单的情况0.1,无论可用的位数是多少,都不能表示为固定长度的浮点数.这与使用1/7这样的分数无法用十进制精确表示是一样的,无论您允许使用多少位数(只要位数是有限的).您可以将其近似为0.142857142857142857 ...一遍又一遍地重复,但无论您持续多久,您都无法完全写出来.

相反,如果一个数字可以完全表示为a float,那么它也可以完全表示为a double.double具有较大的指数范围和更多的尾数位.

对于您的示例,明显差异的原因在于float,0.475与其浮点表示之间的差异处于"正确"方向,因此当截断发生时,它达到了您的预期.当增加可用的精度时,表示"更接近"到0.475但现在在相反的一侧.作为一个很好的例子,假设最接近的浮点数为0.475006,但在最接近的可能值为0.474999时.这会给你看到的结果.

编辑:以下是快速实验的结果:

public class Test {

    public static void main(String[] args)
    {
        float  f = 0.475f;
        double d = 0.475d;

        System.out.printf("%20.16f", f);
        System.out.printf("%20.16f", d);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

  0.4749999940395355  0.4750000000000000
Run Code Online (Sandbox Code Playgroud)

这意味着数字0.475的浮点表示,如果你有大量的位,将只有一点点小于0.475.这在双重表示中看到.然而,第一个'错误'位出现在右边,当截断到适合a时float,它恰好可以达到0.475.这纯属意外.