今天,我正在查看一些C++代码(由其他人编写)并找到了这一部分:
double someValue = ...
if (someValue < std::numeric_limits<double>::epsilon() &&
someValue > -std::numeric_limits<double>::epsilon()) {
someValue = 0.0;
}
Run Code Online (Sandbox Code Playgroud)
我试图弄清楚这是否有意义.
文档epsilon()
说:
该函数返回1和大于1的最小值之间的差值,可以表示[乘双].
这是否也适用于0,即epsilon()
最大值是否大于0?或者有没有之间的数字0
,并0 + epsilon
可以由代表double
?
如果没有,那么比较不等于someValue == 0.0
?
ybu*_*ill 190
假设64位IEEE双,则有52位尾数和11位指数.看看下面的数字:
1.0000 00000000 00000000 00000000 00000000 00000000 00000000 × 2^0 = 1
Run Code Online (Sandbox Code Playgroud)
可表示的最小数字大于1:
1.0000 00000000 00000000 00000000 00000000 00000000 00000001 × 2^0 = 1 + 2^-52
Run Code Online (Sandbox Code Playgroud)
因此:
epsilon = (1 + 2^-52) - 1 = 2^-52
Run Code Online (Sandbox Code Playgroud)
0和epsilon之间有数字吗?很多......例如,最小正可表示(正常)数字是:
1.0000 00000000 00000000 00000000 00000000 00000000 00000000 × 2^-1022 = 2^-1022
Run Code Online (Sandbox Code Playgroud)
实际上有大约(1022 - 52 + 1)×2^52 = 4372995238176751616
0到epsilon之间的数字,大约是所有可表示数字的47%......
Ste*_*sop 17
测试当然不一样someValue == 0
.浮点数的整个概念是它们存储指数和有效数.因此,它们表示具有一定数量的二进制有效精度数值的值(在IEEE双精度的情况下为53).可表示的值在0附近比在1附近密集得多.
要使用更熟悉的十进制系统,假设您使用指数存储"4个有效数字"的十进制值.那么接下来的表示值大于1
是1.001 * 10^0
,和epsilon
是1.000 * 10^-3
.但1.000 * 10^-4
也可以表示,假设指数可以存储-4.您可以接受我的说法,IEEE双倍可以存储小于指数的指数epsilon
.
你无法单独从这段代码中看出是否有意义地使用它epsilon
作为界限,你需要查看上下文.这可能是对epsilon
所产生的计算中的误差的合理估计someValue
,并且可能不是.
Ski*_*izz 13
在0和epsilon之间存在数字,因为epsilon是1和可以在1之上表示的下一个最高数字之间的差异,而不是0和可以在0之上表示的下一个最高数字之间的差异(如果是,那个代码会做的很少): -
#include <limits>
int main ()
{
struct Doubles
{
double one;
double epsilon;
double half_epsilon;
} values;
values.one = 1.0;
values.epsilon = std::numeric_limits<double>::epsilon();
values.half_epsilon = values.epsilon / 2.0;
}
Run Code Online (Sandbox Code Playgroud)
使用调试器,在main结束时停止程序并查看结果,您将看到epsilon/2与epsilon,0和1不同.
因此,此函数采用+/- epsilon之间的值并使它们为零.
可以使用以下程序打印数字(1.0,0.0,...)附近的epsilon(最小可能差异)的近似值.它打印出以下输出:
epsilon for 0.0 is 4.940656e-324
epsilon for 1.0 is 2.220446e-16
一点思考清楚地表明,epsilon越小,我们用来查看其epsilon值的数字越小,因为指数可以调整到该数字的大小.
#include <stdio.h>
#include <assert.h>
double getEps (double m) {
double approx=1.0;
double lastApprox=0.0;
while (m+approx!=m) {
lastApprox=approx;
approx/=2.0;
}
assert (lastApprox!=0);
return lastApprox;
}
int main () {
printf ("epsilon for 0.0 is %e\n", getEps (0.0));
printf ("epsilon for 1.0 is %e\n", getEps (1.0));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
53208 次 |
最近记录: |