Превосходная разница при печати Python и С++ удваивается
В настоящее время я удивляюсь этому:
С++ 11
#include <iostream>
#include <iomanip>
#include <limits>
int main()
{
double d = 1.305195828773568;
std::cout << std::setprecision(std::numeric_limits<double>::max_digits10) << d << std::endl;
// Prints 1.3051958287735681
}
Python
>>> repr(1.305195828773568)
'1.305195828773568'
Что происходит, почему дополнительный 1 в С++?
До сих пор я думал, что С++ и Python используют один и тот же 64-битный IEEE-дубликат под капотом; обе функции форматирования должны печатать полную точность.
Ответы
Ответ 1
вы можете заставить python также напечатать 1 (и еще многие из следующих цифр):
print('{:.16f}'.format(1.305195828773568))
# -> 1.3051958287735681
из https://docs.python.org/2/tutorial/floatingpoint.html:
>>> 7205759403792794 * 10**30 // 2**56
100000000000000005551115123125L
В версиях до Python 2.7 и Python 3.1 Python округлил это значение до 17 значащих цифр, давая "0,10000000000000001. В текущие версии, Python отображает значение на основе кратчайшего десятичная дробь, которая правильно вернется к истинному двоичному значению, в результате просто в 0.1.
"распечатать полную точность" сложно: какая полная точность? представление поплавков двоично; только доли степеней 2 могут быть представлены точно (до полной точности); большинство десятичных дробей не могут быть представлены точно в базе 2.
но float в памяти будет одинаковым для python и С++; это просто строковое представление, которое отличается.
Ответ 2
Когда формат заканчивается с использованием нотации с фиксированной точкой, precision()
указывает количество дробных цифр. Поскольку в вашем примере есть дополнительные дробные цифры, создается еще один, чем те, которые могут быть безопасно представлены.
При использовании научной нотации общее число цифр подсчитывается, и вы получите те же цифры, что и оригинал (плюс показатель, конечно). Параметры C и С++ для форматирования чисел с плавающей запятой на самом деле довольно плохи. В частности, нет опции, которая позволяет форматеру принимать правильное количество цифр, хотя базовый алгоритм может фактически определить их.
Ответ 3
Взято из ответа на этот вопрос:
Плавающая точка IEEE 754 выполняется в двоичном формате. Нет точного преобразования из заданного количества бит в заданное число десятичных цифр. 3 бита могут содержать значения от 0 до 7, а 4 бита могут содержать значения от 0 до 15. Значение от 0 до 9 принимает примерно 3,5 бита, но это также не точно.
Число двойной точности IEEE 754 занимает 64 бита. Из них 52 бит посвящены значению (остальные - знаковый бит и показатель степени). Поскольку значение (обычно) нормализуется, подразумевается 53-й бит.
Теперь, учитывая 53 бит и примерно 3,5 бит на цифру, простое деление дает нам 15.1429 цифр точности. Но помните, что 3,5 бит на десятичную цифру - это всего лишь приближение, а не вполне точный ответ.
Этот странный .1429
после того, как вы указали 15 цифр, вероятно, является виновником добавленного 1.
Для чего это стоит, Python написал это на своем сайте:
Исторически, подсказка Python и встроенная функция repr()
выбрали бы одну из 17 значащих цифр, 0.10000000000000001. Начиная с Python 3.1, Python (в большинстве систем) теперь может выбрать самый короткий из них и просто отображать 0,1.