C または C++ を使用して、ループ内のすべての表現可能な 32 ビット浮動小数点数の範囲をインクリメントしたいと考えています。これは、32 ビット整数で表されるすべての個別の値をインクリメントする方法と同様です。
次のようなもの: for(float f = FLOAT_MIN; f < MAX; f = Next_Float(f)) {...}
標準数学ライブラリの「nexttoward」または「nextafter」関数を使用して、そのタスクを達成できると思います。http://www.cplusplus.com/reference/cmath/nextafter/を参照してください。
現在、double または long double を使用して「nexttoward」または「nextafter」関数をテストし、Ubuntu 13.04 で 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:~$
しかし、double の代わりに float を使用しようとすると、「nexttoward」および「nextafter」関数が失敗します。関数は 32 ビット float よりも高い精度の値を返すように見え、戻り値を 32 ビット float に割り当てると、 float は、次に高い値に上がるのではなく、元の値を保持します。サンプル コードと出力を参照してください。
#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」からの 2 番目の出力値の精度が高く、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
すべての 64 ビット倍精度値ではなく、すべての 32 ビット浮動小数点値をインクリメントしたい - すべての倍精度値をインクリメントする時間が長すぎる。
この問題を解決し、32 ビット浮動小数点変数の範囲を反復処理するための効率的で便利で移植可能な方法を実現するにはどうすればよいですか?