Информация об изменениях

Сообщение Re[2]: printf double от 13.04.2019 7:53

Изменено 13.04.2019 8:08 netch80

Re[2]: printf double
Здравствуйте, kov_serg, Вы писали:

BFE>>Как распечатать double со всей возможной точностью?

_>Очень просто https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%BE_%D0%B4%D0%B2%D0%BE%D0%B9%D0%BD%D0%BE%D0%B9_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D1%81%D1%82%D0%B8
_>53*ln(2)/ln(10)=15.95
_>соответственно "%.16g" (16 значащащих цифр) более чем достаточно.

Нет, недостаточно. Нужно 17, а не 16. Доказательство:

#include <stdio.h>

int main() {
  double f1 = 0.3;
  double f2 = 0.1 * 3;
  printf("%.16g\n", f1);
  printf("%.16g\n", f2);
  printf("%.17g\n", f1);
  printf("%.17g\n", f2);
}


Запускаем:

$ ./td
0.3
0.3
0.29999999999999999
0.30000000000000004


Вообще, откуда вы взяли 16, совершенно непонятно. По отношению к double, которое IEEE754 binary 64-bit portable float, есть две константы:

1. Сколько цифр десятичного текстового представления сохранится при любом значении десятичного порядка при конверсии в двоичное представление и обратно (берётся самое короткое из десятичных, которое конвертируется в то же двоичное представление), при умолчательном округлении. Это значение равно 15.

2. Сколько цифр десятичного представления нужно, чтобы произвольное число в двоичном виде перевести в десятичное представление и затем из него — в двоичное, чтобы значение сохранилось. Это число равно 17.

Для сравнения, для single AKA float AKA IEEE754 binary 32-bit portable float — тут будет 6 и 9 — их разность на 1 больше. Для single, очень мало значений, что сохранится только 6 цифр, а не 7, но они таки есть, и это одна из причин критики формата и стандарта в целом: сделали бы significand не 23 бита, а 24 — размах порядка бы уменьшился (10^19 вместо 10^38), но точность была бы лучше формализуемой. (Я с этой критикой не согласен, но она достаточно активно звучит.)
Re[2]: printf double
Здравствуйте, kov_serg, Вы писали:

BFE>>Как распечатать double со всей возможной точностью?

_>Очень просто https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%BE_%D0%B4%D0%B2%D0%BE%D0%B9%D0%BD%D0%BE%D0%B9_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D1%81%D1%82%D0%B8
_>53*ln(2)/ln(10)=15.95
_>соответственно "%.16g" (16 значащащих цифр) более чем достаточно.

Нет, недостаточно. Нужно 17, а не 16. Доказательство:

#include <stdio.h>

int main() {
  double f1 = 0.3;
  double f2 = 0.1 * 3;
  printf("%.16g\n", f1);
  printf("%.16g\n", f2);
  printf("%.17g\n", f1);
  printf("%.17g\n", f2);
}


Запускаем:

$ ./td
0.3
0.3
0.29999999999999999
0.30000000000000004


Вообще, откуда вы взяли 16, совершенно непонятно. По отношению к double, которое IEEE754 binary 64-bit portable float, есть две константы:

1. Сколько цифр десятичного текстового представления сохранится при любом значении десятичного порядка при конверсии в двоичное представление и обратно (берётся самое короткое из десятичных, которое конвертируется в то же двоичное представление), при умолчательном округлении. Это значение равно 15. Константа — DBL_DIG из <float.h>.

2. Сколько цифр десятичного представления нужно, чтобы произвольное число в двоичном виде перевести в десятичное представление и затем из него — в двоичное, чтобы значение сохранилось, при умолчательном округлении. Это число равно 17. Константа — DBL_DECIMAL_DIG из <float.h>.

Для сравнения, для single AKA float AKA IEEE754 binary 32-bit portable float — тут будет 6 и 9 (FLT_DIG, FLT_DECIMAL_DIG соответственно) — их разность на 1 больше. Для single, очень мало значений, что сохранится только 6 цифр, а не 7, но они таки есть, и это одна из причин критики формата и стандарта в целом: сделали бы significand не 23 бита, а 24 — размах порядка бы уменьшился (10^19 вместо 10^38), но точность была бы лучше формализуемой. (Я с этой критикой не согласен, но она достаточно активно звучит.)