Reputation: 2087
What are the smallest positive values in C++ for which their multiplicative inverse will still be finite?
Have tried numeric_limits<double>::epsilon()
but it isn't it - am getting positive values for much smaller values than that.
#include <limits>//is it here?
void tfuuuuu()
{
double d_eps,invd_eps;
float f_eps,invf_eps;
invd_eps = 1.0/d_eps;//invd_eps should be finite
invf_eps = 1.f/f_eps;//invf_eps should be finite
}
Upvotes: 3
Views: 3259
Reputation: 11430
I doubt there is a standard library function for finding the number you need, however, it is not too hard to find the needed value using a simple binary search:
#include <iostream>
#include <cmath>
#include <typeinfo>
template<typename T> T find_magic_epsilon(T from, T to) {
if (to == std::nextafter(from, to)) return to;
T mid = (from + to)/2;
if (std::isinf((T)1.0/mid)) return find_magic_epsilon<T>(mid, to);
else return find_magic_epsilon<T>(from, mid);
}
template<typename T> T meps() {
return find_magic_epsilon<T>(0.0, 0.1);
}
template<typename T> T test_meps() {
T value = meps<T>();
std::cout << typeid(T).name() << ": MEPS=" << value
<< " 1/MEPS=" << (T)1.0/value << " 1/(MEPS--)="
<< (T)1.0/std::nextafter(value,(T)0.0) << std::endl;
}
int main() {
test_meps<float>();
test_meps<double>();
test_meps<long double>();
return 0;
}
The output of the script above:
f: MEPS=2.93874e-39 1/MEPS=3.40282e+38 1/(MEPS--)=inf
d: MEPS=5.56268e-309 1/MEPS=1.79769e+308 1/(MEPS--)=inf
e: MEPS=8.40526e-4933 1/MEPS=1.18973e+4932 1/(MEPS--)=inf
Upvotes: 3
Reputation: 2660
Here is a starting point to answer your question. I have simply divided by 2. Once you get to dividing by 2^^148, you come pretty close. You could then iteratively move closer and print out the hex representation of the number to see what the compiler is doing:
#include <iostream>
#include <stdio.h>
#include <limits>//is it here?
int main() {
double d_eps,invd_eps;
float f_eps,invf_eps;
invf_eps = 1.f/f_eps;//invf_eps should be finite
float last_seed = 0;
float seed = 1.0;
for(int i = 0; i < 1000000; i++) {
last_seed = seed;
seed = seed/2;
if(seed/2 == invd_eps) {
printf("Breaking at i = %d\n", i);
printf("Seed: %g, last seed: %g\n", seed, last_seed);
break;
}
}
printf("%f, %lf, %f, %lf\n\n", f_eps, d_eps, invf_eps, invd_eps);
return 0;
}
Output:
Breaking at i = 148
Seed: 1.4013e-45, last seed: 2.8026e-45
0.000000, 0.000000, inf, 0.000000
Process finished with exit code 0
Upvotes: 2