Из Компьютерное представление чисел с плавающей запятой Я изучил представление компьютера с плавающей запятой.
В соответствии с руководством, для 32-разрядного числа с плавающей запятой, наименьшее положительное нормализованное число, которое может быть сохранено,2 ^ (- 126) ,, а наибольшее нормированное число - (2-2 ^ (- 23)) * 2 ^ (127) ≈ 2 ^ (128).Однако точность ограничена 23-битным значением.
По моему мнению, 32-битный float может представлять 2 ^ 60 безо всякой ошибки, потому что:
- Знак: 1
- Экспонента: 10111011 (десятичное 187, т.е. 60 + 127)
- Значения: 0000 ... 0000 (23 нуля)
Вполне достаточно использовать показатель степени и скрытый бит (1) иззначимо представлять 2 ^ 60.
Мой тестовый код выглядит следующим образом (VS2013 + win10):
#include <iostream>
#include <math.h>
#include <bitset>
using namespace std;
int main()
{
union
{
float input; // assumes sizeof(float) == sizeof(int)
int output;
} data;
data.input = pow(2., 60.);
std::bitset<sizeof(float) * CHAR_BIT> bits(data.output);
std::cout << "Total: " << bits << std::endl;
cout << "Sign: " << bits[31] << endl << "Exponent: ";
for (int i = 30; i > 22; i--)
{
cout << bits[i];
}
cout << endl << "Significand: ";
for (int i = 22; i >= 0; i--)
{
cout << bits[i];
}
cout << endl;
cout.precision(20);
cout << data.input << endl;
printf("%f", data.input);
}
И я получаю вывод:
Total: 01011101100000000000000000000000
Sign: 0
Exponent: 10111011
Significand: 00000000000000000000000
1152921504606847000
1152921504606847000.000000
Я печатаю двоичное представление, и это правильно,Но я озадачен, почему последние три цифры равны нулю.Правильный вывод должен быть 1152921504606846976.
Кроме того, я изменяю код следующим образом:
#include <iostream>
#include <math.h>
#include <bitset>
using namespace std;
int main()
{
for (int i = 1; i < 65; i++)
{
union
{
float input; // assumes sizeof(float) == sizeof(int)
int output;
} data;
data.input = pow(2, i);
std::bitset<sizeof(float) * CHAR_BIT> bits(data.output);
cout.precision(20);
cout << i << ": " << data.input << endl;
//printf("%f\n", data.input);
}
}
И вывод:
1: 2
2 : 4
3 : 8
......
55 : 36028797018963968
56 : 72057594037927936
57 : 144115188075855870
58 : 288230376151711740
59 : 576460752303423490
60 : 1152921504606847000
61 : 2305843009213694000
62 : 4611686018427387900
63 : 9223372036854775800
64 : 18446744073709552000
Ноль начинает появлятьсяиз 2 ^ 57.Кто-нибудь может сказать мне, почему это произошло?