C++ には、任意のサイズの整数を保持できる bigint クラスがあります。
大きな float または double の数値を bigint に変換したいと思います。私は作業方法を持っていますが、それは少しハックです。IEEE 754 数値仕様を使用して、入力数値の 2 進符号、仮数、および指数を取得しました。
コードは次のとおりです (Sign はここでは無視されますが、重要ではありません)。
float input = 77e12;
bigint result;
// extract sign, exponent and mantissa,
// according to IEEE 754 single precision number format
unsigned int *raw = reinterpret_cast<unsigned int *>(&input);
unsigned int sign = *raw >> 31;
unsigned int exponent = (*raw >> 23) & 0xFF;
unsigned int mantissa = *raw & 0x7FFFFF;
// the 24th bit is always 1.
result = mantissa + 0x800000;
// use the binary exponent to shift the result left or right
int shift = (23 - exponent + 127);
if (shift > 0) result >>= shift; else result <<= -shift;
cout << input << " " << result << endl;
動作しますが、かなり醜く、移植性がどの程度かわかりません。これを行うより良い方法はありますか?float または double からバイナリの仮数部と指数部を抽出する、より醜く移植性の低い方法はありますか?
答えてくれてありがとう。後世のために、frexp を使用したソリューションを次に示します。ループのために効率が低下しますが、float と double の両方で機能し、reinterpret_cast を使用せず、浮動小数点数表現の知識に依存しません。
float input = 77e12;
bigint result;
int exponent;
double fraction = frexp (input, &exponent);
result = 0;
exponent--;
for (; exponent > 0; --exponent)
{
fraction *= 2;
if (fraction >= 1)
{
result += 1;
fraction -= 1;
}
result <<= 1;
}