没有十进制模块的python中的十进制精度

时间:2012-10-23 19:11:17

标签: python python-3.x

我对Python很新,并且想知道如何在不使用任何十进制模块或浮点数的情况下控制任何给定数字的小数精度(例如:“%4f”%n)。

示例(编辑):

输入(2/7)

  

... 0.28571428571

输入(1/3)

  

... 0.33333333333333

我希望它们能够达到千位小数点或任何小数点。我想用一段时间作为一个受控制的循环,但我不确定如何这样做。感谢

编辑:我没有使用十进制模块的原因是我可以概念化这些类型的事物背后的算法/逻辑。只是想真正理解事物背后的逻辑。

3 个答案:

答案 0 :(得分:7)

我们可以使用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

答案 1 :(得分:5)

没有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

答案 2 :(得分:0)

虽然其他答案使用非常大的值来处理精度,但这会实现长时间划分。

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

因为它是除法算法,所以每个数字都是正确的,你可以得到余数(不同于不具有余数的地板划分)。这里的精度我实现为小数点后的位数。

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