В C ++ у меня есть класс bigint, который может содержать целое число произвольного размера.
Я хотел бы преобразовать большие числа с плавающей точкой или двойные числа в bigint.
У меня есть метод работы, но это немного взломать. Я использовал спецификацию числа IEEE 754, чтобы получить двоичный знак, мантиссу и экспоненту входного числа.
Вот код (здесь знак игнорируется, это не важно):
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;
Это работает, но довольно уродливо, и я не знаю, насколько это портативно. Есть лучший способ сделать это? Есть ли менее уродливый, портативный способ извлечь двоичную мантиссу и экспоненту из числа с плавающей или двойной?
Спасибо за ответы. Для потомков, вот решение с использованием frexp. Он менее эффективен из-за цикла, но работает как для чисел с плавающей точкой, так и для двойных, не использует 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;
}