简体   繁体   English

Python中的小数位数

[英]Decimal places in Python

I am trying to put all the decimal places of 1/n into a list in Python. 我试图将1/n所有小数位放入Python的列表中。

def dec(n):

    result = float(1) / n
    while (result >= 1):
        result = result - 1

    while (result != 0):
        result = result * 10
        decimals = int(result)
        yield(decimals)
        result = result - decimals

However, when I tried list(dec(3)) , it doesn't give me a list full of 3s but instead something like [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 7, 2] 然而,当我尝试list(dec(3)) ,它并没有给我一个完整的3s列表,而是像[3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 7, 2] 3,3,3,3,3,3,3,3,3,3,3] [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 7, 2]

How should I fix this? 我该怎么解决这个问题?

Since Python floats are represented in binary, float representations of fractions are not just inexact - decimal approximation are often just as inexact - but inexact in a counter-intuitive way. 由于Python浮点数以二进制表示,因此分数的浮点表示不仅仅是不精确的 - 十进制近似通常也是不精确的 - 但是以反直觉的方式不精确。 We are used to approximating a fraction like 1/3 as something like 0.3333333333, or 33333333333/10**10 (assuming 10 significant digits). 我们习惯于将像1/3这样的分数近似为0.3333333333或33333333333/10 ** 10(假设10位有效数字)。 However, the binary floating-point used by Python represents numbers as fractions with a power-of-two denominator. 但是,Python使用的二进制浮点数表示为具有二次幂分母的分数。 In this representation, 1/3 is approximated as 6004799503160661/2**54, and the digits in your output come from that fraction. 在此表示中,1/3近似为6004799503160661/2 ** 54,输出中的数字来自该分数。

To calculate the digits of a decimal approximation of the fraction 1/3, import the decimal module and replace float(1) with decimal.Decimal(1) . 要计算分数1/3的十进制近似值的数字,请导入decimal模块并将decimal float(1)替换为decimal.Decimal(1) The Decimal type was designed with the express goal of supporting what you're attempting to do here, ie getting results that work the same way as pencil-and-paper calculations with algorithms taught in school. Decimal类型的设计明确目标是支持您在这里尝试做的事情,即获得与铅笔和纸张计算相同的结果与学校教授的算法。

The Decimal instance will of course contain a limited number of digits, which are for 1/3 repeated infinitely. Decimal实例当然包含有限数量的数字,这些数字是无限重复的1/3。 To be able to access digits without limit, import fractions and use fractions.Fraction() . 为了能够无限制地访问数字,导入fractions并使用fractions.Fraction() In that case, the sequence produced by the generator will be infinite and you won't be able to convert it to a list, but you will still be able to iterate over it and analyze as much of it as you need. 在这种情况下,生成器生成的序列将是无限的,您将无法将其转换为列表,但您仍然可以迭代它并根据需要分析它。

I'm assuming you're using Python 3, since you've got only a single "/". 我假设你使用的是Python 3,因为你只有一个“/”。 You'll note that float(1)/3*100000000 = 33333333.333333332. 你会注意到float(1)/ 3 * 100000000 = 33333333.333333332。 This is likely due to the vagaries of binary representation of decimal fractions, because you run out of bits for precision in the width of the float. 这可能是由于十进制分数的二进制表示的变幻莫测,因为你的浮点宽度精度不足。

So, you'd be better off handling it as a string, and converting that to a list: 因此,您最好将其作为字符串处理,并将其转换为列表:

list(str(float(1)/3))[2:]

['3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3']

You are trying to present the rational number as a repeating decimal . 您试图将有理数表示为重复小数 And you need to know that: 你需要知道:

Every rational number is either a terminating or repeating decimal. 每个有理数都是终止或重复小数。

So you do not need to store all the digits there (non repeating part and repeating part). 因此您不需要存储所有数字(非重复部分和重复部分)。 Another important point is that if you have m/n then your repeating part is at maximum n-1 length. 另一个重要的一点是,如果你有m/n那么你的重复部分最长为n-1

Because you are basically asking for solution for project Euler 26 task, I will not post it, but rather will give you a link with some explanation . 因为你基本上是要求项目Euler 26任务的解决方案,我不会发布它,而是会给你一些解释链接

Floating point arithmetic is necessarily inaccurate. 浮点运算必然是不准确的。 One way to compute the digits exactly is to use the division algorithm you probably learnt at school. 精确计算数字的一种方法是使用您在学校可能学到的分割算法。

Here's an implementation: 这是一个实现:

def dec(n):
    v = 1
    while v:
        v *= 10
        yield v // n
        v %= n

You can test it like this, which shows the first 40 digits for 1/3, 1/5, 1/7 and 1/11. 您可以像这样测试它,它显示前1/40,1 / 5,1 / 7和1/11的40位数字。

import itertools

for i in [3, 5, 7, 11]:
    print '1/%d = 0.%s' % (i, ''.join(map(str, itertools.islice(dec(i), 40))))

The output is: 输出是:

1/3 = 0.3333333333333333333333333333333333333333
1/5 = 0.2
1/7 = 0.1428571428571428571428571428571428571428
1/11 = 0.0909090909090909090909090909090909090909

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM