Разве double не может представить любое число 2^n без проблем точности? п естественно
Этот код:
double x = 2.0;
for(int i = 1 ; i<1024 ; i+=i) {
Console.WriteLine( String.Format( "2^{0} = {1:F0}", i, x ) );
x*=x;
}
Выходы:
2^1 = 2
2^2 = 4
2^4 = 16
2^8 = 256
2^16 = 65536
2^32 = 4294967296
2^64 = 18446744073709600000
2^128 = 340282366920938000000000000000000000000
2^256 = 115792089237316000000000000000000000000000000000000000000000000000000000000000
2^512 = 13407807929942600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Я думал, что формула двойника sign * 2 ^ exponent * fraction
; Проиллюстрировать мою ситуацию; С настройкой fraction
в 0.5
, знак к положительному, и путем установки exponent
к любому значению между -1024
в 1023
Я могу представить любой 2^n
номер, который находится в exponent
ассортимент; Что не так с этим выводом? Является ли формула неполной?
4 ответа
double
может представлять степени 2 точно, как показано в следующем коде (который использует Jon Skeet's DoubleConverter
учебный класс):
Console.WriteLine(String.Format("2^{0} = {1}", i, DoubleConverter.ToExactString(x)));
Для спецификатора F0, почему разработчики.NET решили округлить значение после 15 наиболее значимых десятичных цифр?
Мое предположение: отображение точного значения (например, 18446744073709551616) может означать, что double
является точным для всех этих цифр, когда на самом деле double
не может различить это значение и 18446744073709600000. Кроме того, отображение округленного значения согласуется с экспоненциальной нотацией: 1.84467440737096E+19.
Ответ на ваш вопрос заключается в том, что число с двойной точностью IEEE 754 является 64-битным значением:
- 1 бит это знак
- 11 бит представляют показатель степени
- 52 бита представляют значение (но из-за немного глубокой магии, знак действительно имеет 53 бита точности).
Он может представлять не более 2 64 дискретных значений - так же, как 64-разрядное целое число (и на самом деле меньше из-за таких вещей, как NaN
, положительный и отрицательный ноль и т. д.)
Его диапазон, однако, намного больше, чем у 64-битного целого числа: он может представлять десятичные значения примерно от 10 -308 до 10 +308... хотя и с точностью не более 15-17 десятичных цифр.
С плавающей точкой меняет точность на диапазон. Это компромисс.
См. Бинарный формат с плавающей запятой IEEE-754 двойной точности для более подробной информации.
Более того, прочитайте статью Дэвида Голдберга 1991 года "Что должен знать каждый компьютерщик об арифметике с плавающей точкой":
Аннотация. Арифметика с плавающей точкой рассматривается многими людьми как эзотерический предмет. Это довольно удивительно, потому что с плавающей точкой в компьютерных системах повсеместно: почти каждый язык имеет тип данных с плавающей точкой; компьютеры от ПК до суперкомпьютеров имеют ускорители с плавающей запятой; большинство компиляторов будут время от времени компилировать алгоритмы с плавающей точкой; и практически каждая операционная система должна реагировать на исключения с плавающей точкой, такие как переполнение. Эта статья представляет учебное пособие по аспектам с плавающей запятой, которые оказывают непосредственное влияние на разработчиков компьютерных систем. Он начинается с предыстории представления с плавающей запятой и ошибки округления, продолжается обсуждением стандарта IEEE с плавающей запятой и заканчивается примерами того, как сборщики компьютерных систем могут лучше поддерживать с плавающей запятой.
Дэвид Голдберг. 1991. "Что должен знать каждый компьютерщик об арифметике с плавающей точкой". ACM Comput. Surv. 23, 1 (март 1991), 5-48. DOI = 10.1145 / 103162.103163 http://doi.acm.org/10.1145/103162.103163
http://msdn.microsoft.com/en-us/library/678hzkk9.aspx
Ключевое слово double обозначает простой тип, в котором хранятся 64-битные значения с плавающей точкой. В следующей таблице показана точность и приблизительный диапазон для типа double.
Type
double
Approximate range
±5.0 × 10−324 to ±1.7 × 10308
Precision
15-16 digits
Нет. Ваш аргумент терпит неудачу в "путем установки показателя в любое значение".
Есть ограниченный диапазон exponent
Вы не можете представлять
pow(2, 1000000)
хотя 1000000 натуральное число.