Простой Python. современный стиль программирования - читать онлайн бесплатно полную версию книги . Страница 318

числа, которые мы изучали в школе. Из-за того что компьютеры разрабатывались

для бинарной математики, числа, не являющиеся равными степени двойки, зача-

стую не могут быть выражены точно:

>>> x = 10.0 / 3.0

>>> x

3.3333333333333335

Эй, что это за пятерка в конце? На ее месте должна быть тройка. С помощью

модуля decimal (http://docs.python.org/3/library/decimal.html) вы можете записывать

числа с желаемым уровнем точности. Это особенно важно для расчетов денежных

сумм. Сумма в валюте Соединенных Штатов не может быть меньше 1 цента (сотая

часть доллара), поэтому, если мы подсчитываем количество долларов и центов, нам

нужно считать все до копеечки. Если мы попробуем представить доллары и центы

как значения с плавающей точкой вроде 19,99 или 0,06, то потеряем некоторую

часть точности в последних битах еще до начала вычислений. Как с этим справить-

ся? Легко. Нам нужно использовать модуль decimal:

>>> from decimal import Decimal

>>> price = Decimal('19.99')

>>> tax = Decimal('0.06')

>>> total = price + (price * tax)

>>> total

Decimal('21.1894')

Мы записали цену и налог как строковые значения, чтобы сохранить их точ-

ность. При вычислении переменной total мы обработали все значащие части

цента, но хотим получить ближайшее целое значение цента:

>>> penny = Decimal('0.01')

>>> total.quantize(penny)

Decimal('21.19')

412

Приложение В. Py в науке

Такие же результаты можно получить с помощью старых добрых чисел с пла-

вающей точкой и округлений, но не всегда. Вы можете умножить сумму на 100

и использовать при подсчетах количество центов, но и при таком подходе можете

пострадать. Этот вопрос обсуждается на сайте www.itmaybeahack.com.

Выполняем вычисления для рациональных чисел

с помощью модуля fractions

Вы можете представлять числа как числитель, разделенный на знаменатель, с по-

мощью модуля стандартной библиотеки fractions (http://docs.python.org/3/library/

fractions.html). Рассмотрим пример простой операции умножения 1/3 на 2/3:

>>> from fractions import Fraction

>>> Fraction(1, 3) * Fraction(2, 3)

Fraction(2, 9)

Аргументы с плавающей точкой могут быть неточными, поэтому вы можете

использовать модуль Decimal вместе с модулем Fraction:

>>> Fraction(1.0/3.0)

Fraction(6004799503160661, 18014398509481984)

>>> Fraction(Decimal('1.0')/Decimal('3.0'))

Fraction(3333333333333333333333333333, 10000000000000000000000000000)

Получим наибольший общий делитель для двух чисел с помощью функции gcd:

>>> import fractions

>>> fractions.gcd(24, 16)