Using C or C++, I want to increment over the range of all representable 32 bit floating point numbers in a loop, similarly to the way you might increment over all distinct values represented by a 32 bit integer.
Something like: for(float f = FLOAT_MIN; f < MAX; f = Next_Float(f)) {...}
I think that I could use the "nexttoward" or "nextafter" functions in the standard math library to accomplish that task. See http://www.cplusplus.com/reference/cmath/nextafter/
Now, when I test out the "nexttoward" or "nextafter" functions with doubles or long doubles and compiling with g++ 4.7 on Ubuntu 13.04, I don't run in to any problems. See test code:
#include <math.h>
#include <iostream>
#include <iomanip>
int main ()
{
double f = 0.1;
for(int i = 0; i < 5; ++i)
{
//Marginally increment f in the upper direction.
f = nexttoward(f,999.999);
std::cout << std::setprecision(70) << f << std::endl;
std::cout << nexttoward(f,999.999) << std::endl;
}
return 0;
}
The program's floating point output values increase steadily as expected:
ubuntu@ubuntu:~$ g++ -o temp ~/temp.cpp
ubuntu@ubuntu:~$ ./temp
0.10000000000000001942890293094023945741355419158935546875 0.100000000000000033306690738754696212708950042724609375 0.100000000000000033306690738754696212708950042724609375 0.10000000000000004718447854656915296800434589385986328125 0.10000000000000004718447854656915296800434589385986328125 0.1000000000000000610622663543836097232997417449951171875 0.1000000000000000610622663543836097232997417449951171875 0.10000000000000007494005416219806647859513759613037109375 0.10000000000000007494005416219806647859513759613037109375 0.100000000000000088817841970012523233890533447265625
ubuntu@ubuntu:~$
But when I try using floats instead of doubles, the "nexttoward" and "nextafter" functions fail me - the functions appear to return values of greater precision than 32 bit floats, and when I assign the return values to my 32-bit float, the float retain its original value rather than going up to the next higher value. See example code and output:
#include <math.h>
#include <iostream>
#include <iomanip>
int main ()
{
float f = 0.1f;
for(int i = 0; i < 10; ++i)
{
//Marginally increment f in the upper direction.
f = nexttoward(f,999.999f);
std::cout << std::setprecision(70) << f << std::endl;
std::cout << nexttoward(f,999.999f) << std::endl;
}
return 0;
}
Notice that the second output value from "nexttoward" is of greater precision and that f maintains the same value:
ubuntu@ubuntu:~$ g++ -o temp ~/temp.cpp
ubuntu@ubuntu:~$ ./temp
0.100000001490116119384765625 0.10000000149011613326255343281445675529539585113525390625 0.100000001490116119384765625 0.10000000149011613326255343281445675529539585113525390625 0.100000001490116119384765625 0.10000000149011613326255343281445675529539585113525390625 0.100000001490116119384765625 0.10000000149011613326255343281445675529539585113525390625 0.100000001490116119384765625 0.10000000149011613326255343281445675529539585113525390625 0.100000001490116119384765625 0.10000000149011613326255343281445675529539585113525390625 0.100000001490116119384765625 0.10000000149011613326255343281445675529539585113525390625 0.100000001490116119384765625 0.10000000149011613326255343281445675529539585113525390625 0.100000001490116119384765625 0.10000000149011613326255343281445675529539585113525390625 0.100000001490116119384765625 0.10000000149011613326255343281445675529539585113525390625
I want to increment over all 32-bit floating point values, not all 64-bit double precision values - the time to increment over all the double precision values would be too long.
How do I fix this problem and achieve an efficient, convenient, and portable way to iterate over the range of a 32-bit floating point variable?
The nextafter and nexttoward functions take arguments of type double and return results of type double.
For float, use the corresponding nextafterf and nexttowardf functions.
This is a general rule for almost all math functions declared in <math.h>. For example, there are three square root functions:
sqrtf (for float)sqrt (for double)sqrtl (for long double)(The float and long double versions were added by C99, and may not be supported by all implementations.)
If you use the wrong function for a type, the compiler won't complain; it will quietly convert the argument to the expected type, and convert the result depending on what you do with it.
That's for C. If you use #include <cmath>, C++ adds overloaded versions of the math functions (without the f or l suffix) for types float and long double. So if you compile your code as C++, then these functions should behave as you expect. (There may be a difference between <math.h> and <cmath>; in any case, you should use the latter for C++.)
Your question is tagged both C and C++, which have significant differences in this area.
(C99 also adds a <tgmath.h> header that provides type-specific macros that behave similarly to C++'s overloaded functions.)
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