Используйте больше десятичных знаков в Python - PullRequest
3 голосов
/ 28 сентября 2019

У меня уже есть код, который использует метод деления пополам для определения значения чего-либо, проблема в том, что мне нужно такое точное значение, больше 15 десятичных знаков, и в какой-то момент питон перестает получать меньшие цифры

Мне известна библиотека десятичных дробей, но действительно ли мне нужно переписывать каждый параметр в коде как десятичные дроби (параметр)?потому что у меня много параметров

есть ли способ преобразовать все числа с плавающей точкой в ​​коде в десятичные числа универсально?или есть способ решить эту проблему все вместе, используя другой способ?

62.5
31.25
15.625
23.4375
27.34375
25.390625
26.3671875
25.87890625
25.634765625
25.7568359375
25.81787109375
25.787353515625
25.7720947265625
25.76446533203125
25.760650634765625
25.758743286132812
25.75969696044922
25.759220123291016
25.758981704711914
25.758862495422363
25.758802890777588
25.758832693099976
25.75881779193878
25.75882524251938
25.75882151722908
25.75882337987423
25.758824311196804
25.75882477685809
25.758825009688735
25.758825126104057
25.758825184311718
25.758825155207887
25.758825140655972
25.758825133380014
25.758825137017993
25.758825138836983
25.758825139746477
25.758825140201225
25.75882513997385
25.758825139860164
25.75882513980332
25.7588251397749
25.75882513978911
25.758825139796215
25.758825139792663
25.758825139790886
25.758825139791774
25.75882513979222
25.758825139792442
25.75882513979233
25.758825139792386
25.758825139792414
25.7588251397924
25.758825139792407
25.758825139792403
25.758825139792407
25.758825139792407
25.758825139792407
25.758825139792407
25.758825139792407
25.758825139792407
25.758825139792407

Вы видите, что в какой-то момент Python прекращает изменять значение, потому что он не вычисляет меньшие цифры

спасибо

Ответы [ 2 ]

2 голосов
/ 28 сентября 2019

Для float экземпляров Python использует числа с плавающей запятой на машинном уровне с двойной точностью (double в терминах C).Что именно это, зависит от платформы и компилятора, который создал Python.В наши дни это, скорее всего, 64-битное двоичное двоичное число с двойной точностью .53-битное значение и дает от 15 до 17 значащих десятичных цифр.

Если вы используете numpy, вы можете использовать long double число с плавающей запятой.Это имеет 64-битный sigificand, который дает приблизительно 18 десятичных цифр .

Decimal значения имеют регулируемая точность .По умолчанию это 28 значащих цифр, но вы можете это изменить.Поэтому переход к десятичному типу, вероятно, будет хорошим выбором , если вы можете обойтись стандартными математическими операторами и ограниченным количеством математических функций, которые Decimal поддерживает .Но это действительно означает изменение всего вашего кода.Это часть стандартной библиотеки, которая может быть плюсом.

В качестве альтернативы вы можете посмотреть библиотеку mpmath.Это также позволяет вам установить произвольную точность (по умолчанию это 15 значащих цифр).Он поддерживает гораздо более сложную математику, чем Decimal.Он реализует все функции от math и cmath и более.Но здесь вам также необходимо преобразовать всю программу, чтобы изменить float на тип mpf.По умолчанию mpmath работает с целыми числами внутри.Когда доступно, mpmath использует привязки Python к библиотеке gmp , что делает его намного быстрее, особенно с высокой точностью (> 100 цифр).

Заключение

Если вы хотитеДля большей точности вам придется преобразовать вашу программу в математический модуль произвольной точности.В зависимости от того, сколько math функций вы используете, mpmath выглядит лучше;он поддерживает все функции от math и cmath, а затем некоторые.

Как преобразовать

Полное автоматическое преобразование из float в mpf (или Decimal) типовэто невозможно.Но вы можете получить большую часть пути туда.

Оба Decimal и mpf поддерживают стандартные математические операторы.Таким образом, вы не должны менять их.Вам нужно взглянуть на места, где вы создаете или ввод чисел с плавающей запятой, и на места, где вы используете функции из math.

Сначала измените все экземплярыот float( до Decimal( или mpf(.Это заботится о явно созданных числах.Во-вторых, ищите все литералы с плавающей точкой и заменяйте их одинаково.Для этого вы можете использовать функцию поиска и замены вашего редактора или написать небольшой скрипт на Python.Так что это в значительной степени можно автоматизировать.

Затем посмотрите на все функции, которые читают данные из источника (например, из файла или базы данных), и обновите их.Это, вероятно, придется делать вручную, если только они явно не используют float(), и в этом случае они обрабатываются вышеуказанным методом.

Если вы в настоящее время используете модуль math, вам придетсянайдите и замените эти функции их эквивалентами в выбранном модуле.В этом случае поисковая часть может быть легко автоматизирована.Если вы использовали import math, вы можете легко найти «math.», чтобы найти функции, которые необходимо заменить.В этом случае при использовании mpmath вы можете просто заменить "math." на "mpmath.", поскольку mpmath реализует все функции из math.Если вы использовали from math import x, y, z, вам нужно искать x, y и z отдельно.Вы даже можете написать скрипт для перевода math функций в их эквиваленты в Decimal или mpf.В зависимости от размера и сложности вашей кодовой базы, стоит ли это делать.

1 голос
/ 28 сентября 2019

Вы спрашиваете, можете ли вы изменить встроенный тип Python для литералов с плавающей запятой с float на (например) decimal.Decimal.Вы не можете этого сделать.

Другие вопросы, которые следует учитывать

Если decimal.Decimal занимает центральное место в вашем коде, вы можете импортировать его с более коротким именем:

from decimal import Decimal as Dec
x1 = Dec('0.234')
y1 = Dec('4.32')
x2 = Dec('4.321')
y2 = Dec('5.87')

Типовые аннотации могут помочь вам не пропустить преобразования:

def distance(x1: Dec, y1: Dec, x2: Dec, y2: Dec) -> Dec:
    return Dec.sqrt((x2 - x1)**2 + (y2 - y1)**2)

Если важна точность, инициализируйте decimal.Decimal строкой вместо float.Число с плавающей точкой не может точно представлять простые числа, как, например, 0,2:

>>> Dec(0.2)
Decimal('0.200000000000000011102230246251565404236316680908203125')
>>> Dec('0.2')
Decimal('0.2')

Вероятно, есть ограниченное количество мест, где вы должны конвертировать в Decimal.Большинство операций с Decimal либо дает новый десятичный знак, либо выдает исключение.

>>> d = distance(x1, y1, x2, y2)
>>> d
Decimal('4.371048958774083555277441787')
>>> (d + x1*x2 + y1*y2**2) / 100
Decimal('1.542359709587740835552774418')

Я знаю, что это не идеально, но это может помочь.

...