今天,我在看一些c++代码(别人写的),发现了这一部分:
double someValue = ...
if (someValue < std::numeric_limits<double>::epsilon() &&
someValue > -std::numeric_limits<double>::epsilon()) {
someValue = 0.0;
}
我在想这到底说得通不合理。
epsilon()的文档说:
该函数返回1与可[用双精度符号]表示的大于1的最小值之间的差值。
这是否也适用于0,即()的最小值大于0?或者有没有0到0 +之间的数可以用双精度数表示?
如果不是,那么比较是不是等同于someValue == 0.0?
Also, a good reason for having such a function is to remove "denormals" (those very small numbers that can no longer use the implied leading "1" and have a special FP representation). Why would you want to do this? Because some machines (in particular, some older Pentium 4s) get really, really slow when processing denormals. Others just get somewhat slower. If your application doesn't really need these very small numbers, flushing them to zero is a good solution. Good places to consider this are the last steps of any IIR filters or decay functions.
请参见:为什么将0.1f更改为0会使性能降低10倍?
和http://en.wikipedia.org/wiki/Denormal_number
Also, a good reason for having such a function is to remove "denormals" (those very small numbers that can no longer use the implied leading "1" and have a special FP representation). Why would you want to do this? Because some machines (in particular, some older Pentium 4s) get really, really slow when processing denormals. Others just get somewhat slower. If your application doesn't really need these very small numbers, flushing them to zero is a good solution. Good places to consider this are the last steps of any IIR filters or decay functions.
请参见:为什么将0.1f更改为0会使性能降低10倍?
和http://en.wikipedia.org/wiki/Denormal_number
假设64位IEEE双精度,则有52位尾数和11位指数。让我们把它分解一下:
1.0000 00000000 00000000 00000000 00000000 00000000 00000000 × 2^0 = 1
大于1的最小可表示数:
1.0000 00000000 00000000 00000000 00000000 00000000 00000001 × 2^0 = 1 + 2^-52
因此:
epsilon = (1 + 2^-52) - 1 = 2^-52
在0和之间有数字吗?很多……例如,最小正可表示(正常)数为:
1.0000 00000000 00000000 00000000 00000000 00000000 00000000 × 2^-1022 = 2^-1022
事实上,在0和之间有(1022 - 52 + 1)×2^52 = 4372995238176751616个数字,这是所有正可表示数字的47%…
X和X的下一个值之间的差值根据X而变化。
Epsilon()只是1和下一个1的值之间的差。
0和下一个0值之间的差不是()。
相反,你可以使用std::nextafter来比较双精度值和0,如下所示:
bool same(double a, double b)
{
return std::nextafter(a, std::numeric_limits<double>::lowest()) <= b
&& std::nextafter(a, std::numeric_limits<double>::max()) >= b;
}
double someValue = ...
if (same (someValue, 0.0)) {
someValue = 0.0;
}