Полный ответ занял бы много места.Для начала вам нужно прочитать книгу о численном анализе, которая объясняет, как двоичные типы с плавающей запятой работают и хранятся.Но вот некоторые частичные объяснения.
64-битные значения с плавающей запятой хранятся в двоичном, а не в десятичном виде.Поэтому большая часть того, что говорится о десятичных цифрах, должна быть приблизительной, а не полной историей.
Когда np.finfo(np.complex128).precision
(или что-то еще) говорит, что существует 15 значащих десятичных цифр, это означает, что вы не можете рассчитывать набольше, чем те 15 цифр.Вот пример, взятый из моей консоли IPython.
In [4]: 9.000000000000001
Out[4]: 9.000000000000002
In [5]: 9.000000000000001 == 9.000000000000002
Out[5]: True
Python, который по умолчанию использует 64-битный тип с плавающей запятой для любого числа с десятичной запятой, обрабатывает эти два 16-десятичных числакак идентичные.При использовании числа 9.000000000000001
только первые 15 десятичных цифр гарантированно сохраняются правильно.Все, что после этого не гарантируется, и вы видите, что в этом случае 1
в основном изменяется на 2
.
Иногда вы можете получить больше, чем эти 15 десятичных цифр.Например, поскольку числа хранятся в двоичном формате, число, немного превышающее 1.0
, будет иметь больше двоичных цифр после radix point , чем число, подобное 9.0
.Это связано с тем, что 9
использует 4 двоичные цифры, а 1
использует только одну, поэтому после точки радиуса можно использовать еще 3 двоичные цифры.Итак, давайте посмотрим на мнимую часть вашего числа, 1.9021130325903035
:
In [17]: 1.902113032590303 == 1.9021130325903035
Out[17]: False
In [18]: 1.9021130325903036 == 1.9021130325903035
Out[18]: True
In [19]: 1.902113032590304 == 1.9021130325903035
Out[19]: False
Мы видим, что, хотя число показывает 17 десятичных цифр, когда мы меняем последнюю цифру с 5 на 6, Python не видит изменений,Но есть изменение, если мы округлим это число до 16 десятичных цифр, вверх или вниз.Таким образом, мы можем сказать, что число хранится до 16 десятичных цифр и немного больше.Вот почему, когда я объясняю точность, я говорю, что число с плавающей запятой гарантированно будет иметь 15 значащих десятичных цифр, но может иметь 16-ю, а фактическая точность немного больше этой.Вкратце, существует 15 или 16 значащих десятичных цифр.
В Python есть два основных способа печати числа с плавающей запятой: функция str
и функция repr
.Функция str
просто печатает, так что пользователь может понять результат, не вдаваясь в подробности.Функция repr
дает больше деталей и пытается напечатать настолько много деталей, что сохраненные данные могут быть полностью определены тем, что напечатано.Обратите внимание, что repr
используется незаметно в некоторых случаях, например, при вводе числового значения в консоли или, как вы видели, при помощи проводника переменных в Spyder.
Когда Spyder или Python делает repr
наВаш номер 1.9021130325903035
дает достаточно цифр, чтобы полностью определить номер.Как мы видели выше, если бы он показывал только 16 десятичных цифр, отбрасывая окончательную 5
, результат был бы немного отличным от того, что сохранено.Поэтому Python печатает дополнительную цифру, чтобы вы могли знать, каково значение.Если бы Python напечатал окончательный 6
, а не 5
, значение было бы таким же, но если бы Python пропустил эту цифру полностью, значение было бы изменено.Таким образом, Python через repr
ошибается, давая слишком много цифр.Несмотря на то, что напечатаны 17 цифр, достоверны только 16 из них.
Наконец, ваш CSV-файл показывает 20 десятичных цифр, потому что вы сказали Python отображать 20 десятичных цифр из-за спецификаторов %.20e
в np.savetxt
команда.Эти 20 десятичных цифр не являются всеми " полезными десятичными знаками", несмотря на то, что вы написали.Только первые 16 или 17 полезны в мнимой части, в зависимости от того, как вы определяете «полезный».Python в основном добавил двоичные биты, все нули, к сохраненному значению и вывел его в 20 десятичных цифр.Но эти нулевые двоичные биты не были сохранены в значении.