Не совсем специфично для реализации Python, но должно применяться к любым функциям с плавающей запятой для десятичных строковых функций.
Число с плавающей запятой, по сути, является двоичным числом, но в научной записи с фиксированным пределом значащих цифр.
Обращение любого числа, имеющего множитель простого числа, которое не используется совместно с основанием, всегда приводит к повторяющемуся представлению точки. Например, 1/7 имеет главный множитель 7, который не используется совместно с 10, и, следовательно, имеет повторяющееся десятичное представление, и то же самое верно для 1/10 с простыми множителями 2 и 5, причем последний не делится с 2 ; это означает, что 0.1 не может быть точно представлено конечным числом битов после точки точки.
Поскольку 0.1 не имеет точного представления, функция, которая преобразует аппроксимацию в строку десятичной точки, обычно пытается аппроксимировать определенные значения, чтобы они не получали неинтуитивных результатов, таких как 0.1000000000004121.
Так как с плавающей запятой находится в научной нотации, любое умножение на степень основания влияет только на экспонентную часть числа. Например, 1.231e + 2 * 100 = 1.231e + 4 для десятичной записи, а также 1.00101010e11 * 100 = 1.00101010e101 в двоичной записи. Если я умножу на не-мощность базы, значимые цифры также будут затронуты. Например, 1.2e1 * 3 = 3.6e1
В зависимости от используемого алгоритма он может попытаться угадать общие десятичные дроби, основываясь только на значащих цифрах. И 0.1, и 0.4 имеют одинаковые значащие цифры в двоичном виде, потому что их числа с плавающей точкой по сути являются усечениями (8/5) (2 ^ -4) и (8/5) (2 ^ -6) соответственно. Если алгоритм идентифицирует шаблон 8/5 sigfig как десятичное число 1.6, то он будет работать с 0.1, 0.2, 0.4, 0.8 и т. Д. Он может также иметь магические шаблоны sigfig для других комбинаций, таких как число с плавающей точкой 3, деленное на число с плавающей точкой 10 и другие магические паттерны, статистически вероятные при делении на 10.
В случае 3 * 0,1 последние несколько значащих цифр, вероятно, будут отличаться от деления числа с плавающей точкой на число с плавающей точкой 10, что приведет к тому, что алгоритм не сможет распознать магическое число для константы 0,3 в зависимости от его допуска к потере точности.
Изменить:
https://docs.python.org/3.1/tutorial/floatingpoint.html
Интересно, что существует много разных десятичных чисел, которые имеют одну и ту же ближайшую приблизительную двоичную дробь. Например, числа 0,1 и 0,10000000000000001 и 0,1000000000000000055511151231257827021181583404541015625 все приблизительно равны 3602879701896397/2 ** 55. Поскольку все эти десятичные значения имеют одинаковое приближение, любое из них может отображаться, сохраняя при этом инвариантный x (сохраняющий инвариантный e) ) == х.
Не допускается потеря точности, если значение с плавающей запятой x (0.3) не равно точно числу с плавающей запятой y (0,1 * 3), тогда repr (x) точно не равно repr (y).