添加非常小的 Double 值 (Java)
Addition of very small Double values (Java)
我想知道,为什么我简单地添加一些双精度值会导致 Java 中出现以下结果:
double a = 1 + 1E-10; // 1.0000000001 (as expected)
double b = 1 + 1E-15; // 1.000000000000001 (as expected)
double c = 1 + 1E-20; // 1.0 (why?)
我以为我至少可以加上一个Double.MIN_VALUE的值,好像是4.9E-324。
我在这里做错了什么?
你没有做错任何事。小数精度的概念就在眼前。浮点数总是有可能出错的。
并且常见的错误值表示为:
- 1/2E-n <= error <= 1/2E-n
其中 n 是您定义的小数位数。
可以找到更多关于浮点错误的信息here。
正如@Turing85 指出的那样,double
有 11 位指数和 53 位尾数。
我们这里计算的是1.0 + 1E-20。为了表示该数字(比 1.0 更精确),我们至少需要 21 位十进制数字的精度或 71 位。这比尾数中提供的 double
更精确。
因此,与 1.0 + 1E-20 最接近的 可表示 double
数字是 .... 1.0。这就是您得到的结果。
欢迎来到神秘的浮点运算世界。
我想知道,为什么我简单地添加一些双精度值会导致 Java 中出现以下结果:
double a = 1 + 1E-10; // 1.0000000001 (as expected)
double b = 1 + 1E-15; // 1.000000000000001 (as expected)
double c = 1 + 1E-20; // 1.0 (why?)
我以为我至少可以加上一个Double.MIN_VALUE的值,好像是4.9E-324。
我在这里做错了什么?
你没有做错任何事。小数精度的概念就在眼前。浮点数总是有可能出错的。 并且常见的错误值表示为:
- 1/2E-n <= error <= 1/2E-n
其中 n 是您定义的小数位数。
可以找到更多关于浮点错误的信息here。
正如@Turing85 指出的那样,double
有 11 位指数和 53 位尾数。
我们这里计算的是1.0 + 1E-20。为了表示该数字(比 1.0 更精确),我们至少需要 21 位十进制数字的精度或 71 位。这比尾数中提供的 double
更精确。
因此,与 1.0 + 1E-20 最接近的 可表示 double
数字是 .... 1.0。这就是您得到的结果。
欢迎来到神秘的浮点运算世界。