Почему мне нужно 17 значащих цифр (а не 16) для представления двойного? - PullRequest
14 голосов
/ 25 мая 2011

Может ли кто-нибудь привести пример числа с плавающей запятой (двойной точности), для представления которого требуется более 16 значащих десятичных цифр?

Я нашел в этой теме , что иногда вам нужно до 17 цифр, но я не могу найти пример такого числа (мне кажется, 16).

Может кто-нибудь прояснить это?

Большое спасибо!

Ответы [ 5 ]

10 голосов
/ 25 мая 2011

Мой другой ответ был совершенно неверным.

#include <stdio.h>

int
main(int argc, char *argv[])
{
    unsigned long long n = 1ULL << 53;
    unsigned long long a = 2*(n-1);
    unsigned long long b = 2*(n-2);
    printf("%llu\n%llu\n%d\n", a, b, (double)a == (double)b);
    return 0;
}

Скомпилируйте и запустите, чтобы увидеть:

18014398509481982
18014398509481980
0

a и b равны только 2 * (2 ^ 53-1) и 2 * (2 ^ 53-2).

Это 17-значные цифры от 10 до 10. При округлении до 16 цифр они совпадают. Тем не менее, a и b, очевидно, нуждаются только в 53 битах точности для представления в base-2. Поэтому, если вы возьмете a и b и удвоите их, вы получите свой контрпример.

1 голос
/ 26 мая 2011

Правильный ответ - ответ Немо выше.Здесь я просто вставляю простую программу на Фортране, показывающую пример двух чисел, для печати которых требуется 17 цифр точности, показывающий, что для печати чисел двойной точности нужен формат (es23.16), если он не хочет терятьлюбая точность:

program test
implicit none
integer, parameter :: dp = kind(0.d0)
real(dp) :: a, b
a = 1.8014398509481982e+16_dp
b = 1.8014398509481980e+16_dp
print *, "First we show, that we have two different 'a' and 'b':"
print *, "a == b:", a == b, "a-b:", a-b
print *, "using (es22.15)"
print "(es22.15)", a
print "(es22.15)", b
print *, "using (es23.16)"
print "(es23.16)", a
print "(es23.16)", b
end program

печатает:

First we show, that we have two different 'a' and 'b':
a == b: F a-b:   2.0000000000000000     
using (es22.15)
1.801439850948198E+16
1.801439850948198E+16
using (es23.16)
1.8014398509481982E+16
1.8014398509481980E+16
1 голос
/ 25 мая 2011

Я думаю, что парень в этом потоке неверен, и 16 цифр от 10 до 10 всегда достаточно для представления двойного IEEE.

Моя попытка доказательства будет выглядеть примерно так:

Предположим иначе.Тогда обязательно два разных числа с двойной точностью должны быть представлены одним и тем же 16-значным числом с основанием-10.

Но два разных числа с двойной точностью должны отличаться как минимум на одну часть в 2 ^ 53, что больше, чем одна часть в 10 ^ 16.И никакие два числа, отличающиеся более чем на одну часть в 10 ^ 16, не могут округляться до одного и того же 16-значного числа из 10 цифр.

Это не совсем строго и может быть неправильно.: -)

0 голосов
/ 11 мая 2014

Наибольший непрерывный диапазон целых чисел, который может быть точно представлен двойным (8-байтовый IEEE), составляет от -2 ^ 53 до 2 ^ 53 (от -9007199254740992 до 9007199254740992.).Числа -2 ^ 53-1 и 2 ^ 53 + 1 не могут быть точно представлены двойным числом.

Следовательно, не более 16 значащих десятичных разрядов слева от десятичной точки будут точно представлять двойное число внепрерывный диапазон.

0 голосов
/ 17 июля 2011

Окунитесь в основы одинарной и двойной точности и отучите себя от представления о том или ином (16-17) множестве десятичных цифр и начните думать о (53) двоичных цифрах. Необходимые примеры можно найти здесь в stackoverflow, если вы потратите некоторое время на копание.

И я не понимаю, как вы можете присудить лучший ответ любому, кто дает ДЕСЯТИЧНЫЙ ответ без квалифицированных БИНАРНЫХ объяснений. Это просто, но не тривиально.

...