使用 C 或 C++,我想在循环中递增所有可表示的 32 位浮点数的范围,类似于您可能递增由 32 位整数表示的所有不同值的方式。
类似于: for(float f = FLOAT_MIN; f < MAX; f = Next_Float(f)) {...}
我认为我可以使用标准数学库中的“nexttoward”或“nextafter”函数来完成该任务。见http://www.cplusplus.com/reference/cmath/nextafter/
现在,当我在 Ubuntu 13.04 上使用双精度或长双精度测试“nexttoward”或“nextafter”函数并使用 g++ 4.7 进行编译时,我没有遇到任何问题。见测试代码:
#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;
}
程序的浮点输出值按预期稳步增加:
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:~$
但是当我尝试使用浮点数而不是双精度数时,“nexttoward”和“nextafter”函数让我失望了——这些函数似乎返回的值比 32 位浮点数精度更高,当我将返回值分配给我的 32 位浮点数时,浮动保留其原始值,而不是上升到下一个更高的值。查看示例代码和输出:
#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;
}
请注意,“nexttoward”的第二个输出值具有更高的精度,并且 f 保持相同的值:
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
我想增加所有 32 位浮点值,而不是所有 64 位双精度值 - 增加所有双精度值的时间会太长。
如何解决此问题并实现一种高效、方便且可移植的方式来迭代 32 位浮点变量的范围?