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, e.g. by bit shifting? Independent of the compiler, optimization flags, platform...
Thanks for your answers
An experimenter slowly adds tiny amounts of sand to one hand and asks you to say when you notice that one hand feels heavier than the other. The smallest weight difference that you can detect at least half the time is the just noticeable difference.
Just noticeable difference (JND): The smallest detectable difference between two stimuli, or the minimum change in a stimulus that can be correctly judged as different from a reference stimulus; also known as difference threshold.
Weber's Law states that the concept that a just-noticeable difference in a stimulus is proportional to the magnitude of the original stimulus.
A difference threshold is the minimum required difference between two stimuli for a person to notice change 50% of the time (and you already know where that “50% of the time” came from). The difference threshold is also called just noticeable difference, which translates the concept more clearly.
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With