2015-01-23 4 views
0

есть способ ингибирования питона округление, например:Есть ли способ препятствовать округлению в python?

>>> getcontext().prec = 11; print (Decimal(1.1237836550999999999)*10**10) 
11237836551 

мне нужно показать первые 10 знаков после запятой десятичного числа, так что на самом деле мне нужно 11237836550 как выход и мне не нужно, что округление на последняя цифра (в этом случае 0 округляется до 1).

Иногда я могу просто увеличить точность (не в данном случае), а затем выполнить расчет безопасно, как это:

>>> getcontext().prec = 14; print (Decimal(1.12378365509978)*10**10) 
11237836550.998 

Но предположим, что вы не знаете о десятичной части числа после этого '0', например это может быть 1.123783655099999999999999999999999999 ... и так далее, и тогда вы не можете полагаться на это «обходное решение».

Итак, есть ли способ сказать python, «для этого вычисления я не хочу, чтобы какое-либо округление выполнялось, на самом деле я хочу, чтобы вы просто вернули мне необходимое количество десятичных знаков (10 в этом примере), и выбросить что-нибудь еще после этого? »

Я посмотрел здесь Truncating floats in Python, но в основном то, что мне нужно, это не строка усеченного поплавка, а еще одно десятичное число, используемое для выполнения вычислений. Кроме того, trunc функции принятого ответа в посте я связан не буду работать в этом случае вызывают -десятичный округляются только прежде чем он будет передан «F» аргумент функции:

>>> def trunc(f, n): 
...  '''Truncates/pads a float f to n decimal places without rounding''' 
...  return ('%.*f' % (n + 1, f))[:-1] 
... 
>>> trunc(Decimal(1.12378365509978), 10) 
'1.1237836551' # and not 1.1237836550 as needed 

Как могу ли я это сделать?

ответ

2

Является ли это то, что вы искали:

from decimal import * 

getcontext().prec = 103 

def precision(context, prec=100): 

    return Decimal(context).quantize(Decimal('.'+'0'*(prec-1)+'1'), rounding=ROUND_DOWN) 

print precision(Decimal(10).log10()/Decimal(2).log10()) 

Выход:

3.3219280948873623478703194294893901758648313930245806120547563958159347766086252158501397433593701550 
+0

Это кажется более надежным решением, не так ли? – tonix

+0

Как я могу использовать квантование с переменным результатом, то есть результатом выражения, 'Десятичный (math.sqrt (2) + 5) .quantize ('. 00000000001')' дает 'TypeError: преобразование из str в десятичный не поддерживается' – tonix

+1

@ user3019105 Внутри 'quantize'' 'Decimal', не забывайте! 'In [5]: Decimal (math.sqrt (2) + 5) .quantize (Decimal ('. 00000000001'), rounding = ROUND_DOWN)' будет выдавать ваш результат без ошибки 'Out [5]: Decimal (' 6.41421356237 ') ' – dragon2fly

7

Вы проблема не Decimal. Это float. А именно:

>>> 1.1237836550999999999 
1.1237836551 

Купить, если вы:

>>> int(Decimal("1.1237836550999999999")*10**10) 
11237836550 

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

+0

Хорошо, спасибо, всегда ли это работает, даже если у меня есть число с бесконечным 9s? как 1.123783655099999999999999999999 .........? – tonix

+0

Это не работает для '>>> getcontext(). Prec = 11; печать (интермедиат (Decimal (1.123783655099999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999) * 10 ** 10)) 'он по-прежнему выдает' 1.1237836551' – tonix

+1

@ user3019105 вы до сих пор отсутствуют котировки. Используйте строку. Если вы напишете его как есть, он преобразуется в число с плавающей запятой с точностью до машины, прежде чем перейти к конструктору Decimal; Плавки с двойной точностью имеют около ~ 15 знаков после запятой, поэтому все 9, которые вы записали, просто бесполезны. – orion

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