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,则其等效浮点表示也将不准确地存储.
然而,我得到的结果对我来说有点令人不安.我很困惑,如果:
precision意思的理解不正确?float并且double表示不同,除了double有更多位?可以作为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)
精度只意味着更多的位.不能表示为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.这纯属意外.