Вопрос

Поэтому я решил попробовать выполнить домашнее задание по физике, написав несколько скриптов на Python, которые решат за меня задачи.Одна из проблем, с которой я сталкиваюсь, заключается в том, что значимые цифры не всегда получаются правильно.Например, это правильно обрабатывает значимые цифры:

from decimal import Decimal
>>> Decimal('1.0') + Decimal('2.0')
Decimal("3.0")

Но это не так:

>>> Decimal('1.00') / Decimal('3.00')
Decimal("0.3333333333333333333333333333")

Итак, два вопроса:

  1. Прав ли я в том, что это не ожидаемое количество значащих цифр, или мне нужно освежить в памяти математику значащих цифр?
  2. Есть ли способ сделать это без необходимости вручную устанавливать десятичную точность?Конечно, я уверен, что смогу использовать для этого numpy, но я просто хочу знать, есть ли способ сделать это с помощью decimal модуля из любопытства.
Это было полезно?

Решение

Изменение десятичной рабочей точности на 2 цифры нет хорошая идея, если только вы не собираетесь выполнять только одну операцию.

Вы всегда должны выполнять вычисления с более высокой точностью, чем уровень значимости, и округлять только конечный результат.Если выполнять длинную последовательность вычислений и округлять до количества значащих цифр на каждом шаге, будут накапливаться ошибки.Модуль decimal не знает, является ли какая-либо конкретная операция операцией в длинной последовательности или конечным результатом, поэтому он предполагает, что не следует округлять больше, чем необходимо.В идеале нужно было бы использовать бесконечную точность, но это слишком дорого, поэтому разработчики Python остановились на 28 цифрах.

Как только вы получите окончательный результат, вам, вероятно, понадобится квантовать:

>>> (Decimal('1.00') / Decimal('3.00')).quantize(Decimal("0.001"))
Decimal("0.333")

Вам придется отслеживать значимость вручную.Если вы хотите автоматическое отслеживание значимости, вам следует использовать интервальную арифметику.Для Python доступно несколько библиотек, в том числе пи-интервал и мпматематика (который поддерживает произвольную точность).Интервальную арифметику также легко реализовать с помощью библиотеки decimal, поскольку она поддерживает направленное округление.

Вы также можете прочитать Часто задаваемые вопросы по десятичной арифметике:Является ли десятичная арифметика «значимой» арифметикой?

Другие советы

Десятичные знаки не будут выбрасывать такие десятичные знаки.Если вы действительно хотите ограничить точность до 2 d.p.тогда попробуй

decimal.getcontext().prec=2

РЕДАКТИРОВАТЬ:В качестве альтернативы вы можете вызывать quantize() каждый раз, когда вы умножаете или делите (сложение и вычитание сохранят 2 dps).

Просто из любопытства... обязательно ли использовать десятичный модуль?Почему бы не использовать плавающую запятую с округлением чисел до значащих цифр, когда вы готовы их увидеть?Или вы пытаетесь отслеживать важные цифры вычислений (например, когда вам нужно выполнить анализ ошибок результата, вычисляя вычисленную ошибку как функцию неопределенностей, которые вошли в расчет)?Если вам нужна функция округления, которая округляет число слева, а не справа, попробуйте:

def lround(x,leadingDigits=0): 
    """Return x either as 'print' would show it (the default) 
    or rounded to the specified digit as counted from the leftmost 
    non-zero digit of the number, e.g. lround(0.00326,2) --> 0.0033
    """ 
    assert leadingDigits>=0 
    if leadingDigits==0: 
            return float(str(x)) #just give it back like 'print' would give it
    return float('%.*e' % (int(leadingDigits),x)) #give it back as rounded by the %e format  

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

>>> lround(1./3.,2),str(lround(1./3.,2)),str(lround(1./3.,4))
(0.33000000000000002, '0.33', '0.3333')

Десятичная дробь по умолчанию имеет точность 28 знаков.
Единственный способ ограничить количество возвращаемых цифр — изменить точность.

Если я правильно понимаю десятичную дробь, «точность» — это количество цифр после десятичной точки в десятичная система счисления.

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

Мне было бы интересно узнать о модуле Python, который выполняет вычисления с плавающей запятой с учетом значащих цифр.

Что не так с плавающей запятой?

>>> "%8.2e"%  ( 1.0/3.0 )
'3.33e-01'

Он был разработан для вычислений в научном стиле с ограниченным количеством значащих цифр.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top