Десятичная точность в python без десятичного модуля

Я новичок в Python и задавался вопросом, как бы я мог контролировать десятичную точность любого заданного числа без использования десятичного модуля или плавающих точек (например: "% 4f" % n).

Примеры (править):

вход (2/7)

+0,28571428571....

вход (1/3)

+0,33333333333333....

и я хотел, чтобы они составляли тысячу десятичных точек или любую десятичную точку. Я думал использовать некоторое время как управляемый цикл, но я не совсем уверен, как это сделать. Благодаря

edit: Причина, по которой я не использую десятичный модуль, - это то, что я могу концептуализировать алгоритм/логику, лежащую в основе такого типа вещей. Просто пытаюсь понять логику вещей.

3 ответа

Без модуля Decimal (почему?), предполагая Python 3:

def divide(num, den, prec):
 a = (num*10**prec) // den
 s = str(a).zfill(prec+1)
 return s[0:-prec] + "." + s[-prec:]

Благодаря @nneonneo для умной идеи .zfill()!

>>> divide(2,7,1000)
'0.28571428571428571428571428571428571428571428571428571428571428571428571428571
42857142857142857142857142857142857142857142857142857142857142857142857142857142
85714285714285714285714285714285714285714285714285714285714285714285714285714285
71428571428571428571428571428571428571428571428571428571428571428571428571428571
42857142857142857142857142857142857142857142857142857142857142857142857142857142
85714285714285714285714285714285714285714285714285714285714285714285714285714285
71428571428571428571428571428571428571428571428571428571428571428571428571428571
42857142857142857142857142857142857142857142857142857142857142857142857142857142
85714285714285714285714285714285714285714285714285714285714285714285714285714285
71428571428571428571428571428571428571428571428571428571428571428571428571428571
42857142857142857142857142857142857142857142857142857142857142857142857142857142
85714285714285714285714285714285714285714285714285714285714285714285714285714285
7142857142857142857142857142857142857142857'

Предостережение: это использует разделение полов, поэтому divide(2,3,2) даст вам 0.66 вместо 0.67.


Мы можем использовать long для хранения десятичной дроби с высокой точностью и выполнять арифметику. Вот как вы его распечатали:

def print_decimal(val, prec):
 intp, fracp = divmod(val, 10**prec)
 print str(intp) + '.' + str(fracp).zfill(prec)

Использование:

>>> prec = 1000
>>> a = 2 * 10**prec
>>> b = a//7
>>> print_decimal(b, prec)
0.2857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857


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

def divide(num, denom, prec=30, return_remainder=False):
 "long divison"
 remain=lim=0
 digits=[]
 #whole part
 for i in str(num):
 d=0;remain*=10
 remain+=int(i)
 while denom*d<=remain:d+=1
 if denom*d>remain:d-=1
 remain-=denom*d
 digits.append(d)
 #fractional part
 if remain:digits.append('.')
 while remain and lim<prec: d="0;remain*=10" while="" denom*d<="remain:d+=1" if="" denom*d="">remain:d-=1
 remain-=denom*d
 digits.append(d)
 lim+=1
 #trim leading zeros 
 while digits[0]==0 and digits[1]!='.':
 digits=digits[1:]
 quotient = ''.join(list(map(str,digits)))
 if return_remainder:
 return (quotient, remain)
 else:
 return quotient
</prec:>

Потому что это алгоритм деления, каждая цифра будет правильной, и вы можете получить остаток (в отличие от деления полов, у которого не будет остатка). Точность здесь я реализовал как число цифр после десятичного знака.

>>> divide(2,7,70)
'0.2857142857142857142857142857142857142857142857142857142857142857142857'
>>> divide(2,7,70,True)
('0.2857142857142857142857142857142857142857142857142857142857142857142857', 1)

licensed under cc by-sa 3.0 with attribution.