How to determine the minimal noticable change of a double
I have the problem to determine the smallest value eps
for a given double variable v
such that
v+eps != v
Note that this is not the typical problem sheet task since eps
depends on the arbitrary number v
.
This should not be done by seeking this value in a for loop. Is there a fast way to do this, eg by bit shifting? Independent of the compiler, optimization flags, platform...
Thanks for your answers
The C99 function nextafter
is what you need. Alternatively, use Boost.Math's nextafter
. This is implementation defined by definition (it relies on the internal representation of double
in memory).
For a comparison of all methods presented in the answers here at the time of writing, see a live demo to see how the other solutions fail.
For reference, here is the test code if you want to run it on our own system:
#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);
}
I'd use type punning:
double
epsFor( double x )
{
union
{
double d;
unsigned long long i;
} tmp;
tmp.d = x;
++ tmp.i;
double results = tmp.d - x;
return results;
}
(Formally, this is undefined behavior, but in practice, I don't know of a modern compiler where it will fail.)
EDIT:
Note that C++ allows excessive precision in intermediate expressions; since we're concerned here with exact results, the originally posted function could give wrong results if you used it directly in an expression, rather than assigning it to a double
. I've added an assignment in the function to avoid this, but be aware that a lot of compilers are not standard conform in this regard, at least by default. (g++ is a good example of one where you need a special option to have conformant behavior, at least when optimization is turned on. If you're using g++, you must specify the -ffloat-store
option if you want correct results.)
eps = std::numeric_limits<double>::epsilon() * v;
链接地址: http://www.djcxy.com/p/74890.html
上一篇: 使用LoopJ AndroidAsyncHttp从https下载图像资源
下一篇: 如何确定一个double的最小显着变化