2008-09-27 12 views
5

Итак, я решил попытаться решить домашнюю работу по физике, написав скрипты 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 для этого, но я просто хочу знать, есть ли способ сделать это с десятичным модулем из любопытства.

ответ

8

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

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

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

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

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

Вы также можете прочитать Decimal Arithmetic FAQ: Is the decimal arithmetic ‘significance’ arithmetic?

0

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

+0

Это не всегда так. Например: >>> Decimal ('1.0') * Decimal ('1.0') дает десятичное значение («1.00») Возможно, вы говорите это в контексте деления? – 2008-09-27 18:57:15

2

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

decimal.getcontext().prec=2 

EDIT: В качестве альтернативы вы можете вызвать квантование() каждый раз, когда вы умножаете или разрыв (сложение и вычитание сохранят 2 дпс).

+0

Хммм ... так что нет способа заставить это сделать, не требуя, чтобы я установил точность вручную? – 2008-09-27 19:00:30

0

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

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

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

0

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

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

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

+0

Проблема в том, что я все равно буду устанавливать количество значимых цифр вручную. – 2008-09-27 19:38:52

+0

Я уверен, что не вижу, как установка значимых цифр является проблемой. Вам нужно будет расширить свой вопрос, чтобы показать, что вы хотите, и почему вы не можете/не хотите устанавливать значимые цифры. – 2008-09-28 00:01:04

1

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

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') 

 Смежные вопросы

  • Нет связанных вопросов^_^