Невозможно увидеть приближения Python в математических вычислениях - PullRequest
1 голос
/ 25 июня 2009

Проблема: , чтобы увидеть, когда компьютер делает приближение в математических вычислениях, когда я использую Python

Пример проблемы:

Мой старый учитель однажды сказал следующее утверждение

You cannot never calculate 200! with your computer. 

Я не совсем уверен, правда это или нет в наши дни. Кажется, что это так, поскольку я получаю много нулей для этого из скрипта Python .

Как вы можете видеть, когда ваш код Python приближается?

Ответы [ 6 ]

7 голосов
/ 25 июня 2009

Python использует арифметику произвольной точности для вычисления с целыми числами, поэтому он может точно рассчитать 200 !. Для действительных чисел (так называемых с плавающей точкой ) Python не использует точное представление. Он использует двоичное представление под названием IEEE 754 , что по сути является научной нотацией, за исключением базы 2 вместо базы 10.

Таким образом, любое действительное число, которое не может быть точно представлено в базе 2 с точностью 53 бита, Python не может дать точный результат. Например, 0,1 (в базе 10) - это бесконечное десятичное число в базе 2, 0,0001100110011 ..., поэтому оно не может быть точно представлено. Следовательно, если вы вводите в приглашении Python:

>>> 0.1
0.10000000000000001

Результат, который вы получите, будет другим, поскольку он был преобразован из десятичного в двоичное (с точностью до 53 бит) обратно в десятичное. Как следствие, вы получаете такие вещи:

>>> 0.1 + 0.2 == 0.3
False

Хорошее (но продолжительное) чтение см. Что должен знать каждый программист об арифметике с плавающей запятой .

2 голосов
/ 25 июня 2009

Python имеет неограниченные целые размеры в виде типа long . То есть, если это целое число, ограничение размера числа ограничено объемом памяти, доступной для Python.

Когда вы вычисляете большое число, например 200! и вы видите букву L в конце, это означает, что Python автоматически приводил int к long , потому что int был недостаточно большим, чтобы содержать это число.

См. Раздел 6.4 из на этой странице для получения дополнительной информации.

1 голос
/ 25 июня 2009

Python обрабатывает большие числа автоматически (в отличие от языка, подобного C, где вы можете переполнить его типы данных и значения сбрасываются, например, на ноль) - через определенную точку (sys.maxint или 2147483647) он преобразует целое число в "long "(обозначается L после числа), который может быть любой длины:

>>> def fact(x):
...     return reduce(lambda x, y: x * y, range(1, x+1))
... 
>>> fact(10)
3628800
>>> fact(200)
788657867364790503552363213932185062295135977687173263294742533244359449963403342920304284011984623904177212138919638830257642790242637105061926624952829931113462857270763317237396988943922445621451664240254033291864131227428294853277524242407573903240321257405579568660226031904170324062351700858796178922222789623703897374720000000000000000000000000000000000000000000000000L

Длинные числа «просты», с плавающей запятой сложнее, и почти любое компьютерное представление числа с плавающей запятой является приближением, например:

>>> float(1)/3
0.33333333333333331

Очевидно, что вы не можете хранить бесконечное количество 3 в памяти, поэтому он обманывает и округляет его немного.

Возможно, вы захотите взглянуть на модуль десятичный :

  • Десятичные числа могут быть представлены точно. Напротив, числа типа 1.1 не имеют точного представления в двоичной с плавающей запятой. Конечные пользователи обычно не ожидают, что 1.1 будет отображаться как 1.1000000000000001, как это происходит с двоичной плавающей запятой.
  • В отличие от двоичной аппаратной части с плавающей запятой, десятичный модуль имеет изменяемую пользователем точность (по умолчанию до 28 разрядов), которая может быть настолько большой, насколько это необходимо для данной проблемы
1 голос
/ 25 июня 2009

Без какого-либо пояснения к этому утверждению оно явно ложно. Исходя из личного опыта, первые уроки программирования (в конце 1980-х) включали в себя решение очень похожих, если не точно таких же проблем. В общем, чтобы знать какое-то устройство, которое выполняет вычисления, а не приближения, вы должны доказать (в математическом смысле доказательства), что это не так.

Целочисленные типы Python (названные int и long в 2.x, оба сложены в тип int в 3.x) очень хороши и не переполняются, как, например, int введите C. Если вы делаете очевидное из print 200 * 199 * 198 * ..., оно может быть медленным, но оно будет точным. Аналогично сложение, вычитание и модуль являются точными. Деление - это смешанный пакет, так как есть два оператора, / и //, и они претерпели изменения в 2.x - в общем, вы можете рассматривать его только как неточное.

Если вы хотите больше контроля, но не хотите ограничивать себя целыми числами, посмотрите на модуль decimal.

1 голос
/ 25 июня 2009

200! это действительно очень большое число.

Если диапазон 64-разрядного двойного кода IEEE равен 1,7E +/- 308 (15 цифр), вы можете увидеть, что самый большой факториал, который вы можете получить, составляет около 170!

Python может обрабатывать числа произвольного размера, как и Java с его BigInteger.

1 голос
/ 25 июня 2009

См. Обработка очень больших чисел в Python .

В Python есть класс BigNum для удержания 200! и будет использовать его автоматически.

Утверждение вашего учителя, хотя и не совсем верно, в целом верно. У компьютеров есть ограничения, и хорошо знать, кто они. Помните, что каждый раз, когда вы добавляете другое целое число для хранения данных, вы можете хранить число, которое в 2 ^ 32 (4 миллиарда +) раз больше. Трудно понять, сколько еще чисел - но математика становится медленнее, когда вы добавляете больше целых чисел для хранения точного значения очень большого числа.

В качестве примера (что вы можете хранить с 1000 битами)

>>> 2 << 1000
2143017214372534641896850098120003621122809623411067214887500776740702102249872244986396
7576313917162551893458351062936503742905713846280871969155149397149607869135549648461970
8421492101247422837559083643060929499671638825347975351183310878921541258291423929553730
84335320859663305248773674411336138752L

Я попытался проиллюстрировать, насколько большим может быть число, хранящееся в 10000 битах или даже в 8 000 000 бит (мегабайт), но это число занимает много страниц.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...