eps
我有问题要确定给定双变量的最小值,v
这样
v+eps != v
请注意,这不是典型的问题表任务,因为eps
取决于任意数字v
。
这不应该通过在 for 循环中查找该值来完成。有没有一种快速的方法来做到这一点,例如通过位移?独立于编译器、优化标志、平台......
感谢您的回答
eps
我有问题要确定给定双变量的最小值,v
这样
v+eps != v
请注意,这不是典型的问题表任务,因为eps
取决于任意数字v
。
这不应该通过在 for 循环中查找该值来完成。有没有一种快速的方法来做到这一点,例如通过位移?独立于编译器、优化标志、平台......
感谢您的回答
C99 功能nextafter
正是您所需要的。或者,使用 Boost.Math 的nextafter
. 这是由定义定义的实现(它依赖double
于内存中的内部表示)。
有关在撰写本文时此处答案中提供的所有方法的比较,请查看现场演示以了解其他解决方案如何失败。
作为参考,如果您想在我们自己的系统上运行它,这里是测试代码:
#include <cmath>
#include <cfloat>
#include <limits>
#include <iostream>
using std::cout;
#include <iomanip>
using std::setprecision;
#include <boost/math/special_functions/next.hpp>
double
epsFor( double x )
{
union
{
double d;
unsigned long long i;
} tmp;
tmp.d = x;
++ tmp.i;
return tmp.d - x;
}
void test(double d)
{
double d1 = std::nextafter(d,DBL_MAX);
double d2 = d+std::numeric_limits<double>::epsilon() * d;
double d3 = d+epsFor(d);
double d4 = boost::math::nextafter(d, DBL_MAX);
cout << setprecision(40)
<< "For value of d = " << d << '\n'
<< " std::nextafter: " << d1 << '\n'
<< " Boost solution: " << d4 << '\n'
<< " undefined beh.: " << d3 << '\n'
<< " numeric_limits: " << d2 << '\n';
}
int main()
{
test(0.1);
test(986546357654.354687);
}
我会使用类型双关语:
double
epsFor( double x )
{
union
{
double d;
unsigned long long i;
} tmp;
tmp.d = x;
++ tmp.i;
double results = tmp.d - x;
return results;
}
(形式上,这是未定义的行为,但实际上,我不知道现代编译器会在哪里失败。)
编辑:
请注意,C++ 允许中间表达式的精度过高;由于我们在这里关注的是精确结果,因此如果您直接在表达式中使用最初发布的函数而不是将其分配给double
. 我在函数中添加了一个赋值以避免这种情况,但请注意,很多编译器在这方面并不符合标准,至少在默认情况下是这样。(g++ 是一个很好的例子,你需要一个特殊的选项来获得一致的行为,至少在优化打开时。如果你使用的是 g++,
-ffloat-store
如果你想要正确的结果,你必须指定选项。)
eps = std::numeric_limits<double>::epsilon() * v;