如何确定一个double的最小显着变化
我有问题来确定给定双变量v
的最小值eps
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;
链接地址: http://www.djcxy.com/p/74889.html
上一篇: How to determine the minimal noticable change of a double