将pi打印到指定小数位数

11

w3resources网站上的挑战之一是将圆周率打印到'n'个小数位。这是我的代码:

from math import pi

fraser = str(pi)

length_of_pi = []

number_of_places = raw_input("Enter the number of decimal places you want to 
see: ")

for number_of_places in fraser:
    length_of_pi.append(str(number_of_places))

print "".join(length_of_pi)

出于某种原因,它会自动打印圆周率而不考虑任何输入。希望能得到帮助 :)


挑战是要打印出舍入到n个小数位的π,还是打印出π的前n个小数位? - glibdud
9个回答

19

使用np.pimath.pi等提出的解决方案仅适用于双精度(约14个数字),如果需要更高的精度,需要使用多精度计算,例如mpmath软件包。

>>> from mpmath import mp
>>> mp.dps = 20    # set number of digits
>>> print(mp.pi)
3.1415926535897932385

使用np.pi会得到错误的结果。

>>> format(np.pi, '.20f')
3.14159265358979311600

相对于真实值进行比较:

3.14159265358979323846264338327...

13

为什么不直接使用 number_of_places 格式化:

''.format(pi)
>>> format(pi, '.4f')
'3.1416'
>>> format(pi, '.14f')
'3.14159265358979'

更一般地说:

>>> number_of_places = 6
>>> '{:.{}f}'.format(pi, number_of_places)
'3.141593'
在你原来的方法中,我猜测你试图使用number_of_places作为循环的控制变量来选择几个数字,这样做相当笨拙,但在你的情况下并不起作用,因为用户输入的初始number_of_digits从未被使用,取而代之的是来自pi字符串的迭代值。

我认为这有点违背了整个挑战的初衷?是否有一种方法可以根据给定的输入修改小数位数? - Fraser
@Fraser 在答案中还有一个“更普遍”的部分 :) - Moses Koledoye
@MosesKoledoye 谢谢你的回答,这也回答了我的问题。我是一个完全的新手。我试图直接将输入内容放入(pi, ' .inputf)中,当然它没有起作用。你在回答中通用部分使用的 '{ }' 是一个改变游戏规则的东西。我在哪里可以学到更多关于这个的知识?谢谢。 - Bowen Liu

2
例如,mpmath包的最初回答。
from mpmath import mp
def a(n):
   mp.dps=n+1
   return(mp.pi)

2

非常好的答案!有很多方法可以实现这个目标。请看下面我使用的方法,它适用于任意数量的小数位直至无限:

#import multp-precision module
from mpmath import mp
#define PI function
def pi_func():
    while True:
        #request input from user
        try:
             entry = input("Please enter an number of decimal places to which the value of PI should be calculated\nEnter 'quit' to cancel: ")
             #condition for quit
             if entry == 'quit':
                 break
             #modify input for computation
             mp.dps = int(entry) +1
         #condition for input error
         except:
                print("Looks like you did not enter an integer!")
                continue
         #execute and print result
         else:
              print(mp.pi)
              continue

祝你好运,朋友!


1
这是我所做的,非常基础但有效(最多15位小数):
pi = 22/7
while True:

    n = int(input('Please enter how many decimals you want to print: '))

    if n<=15:
        print('The output with {} decimal places is: '.format(n))
        x = str(pi)
        print(x[0:n+2])
        break
    else:
        print('Please enter a number between 0 and 15')

1
问题是打印任意N位小数的圆周率,而不是前15位。但是在这种精神上的一些东西应该可以工作。 - Jeremad
是的!如果我们在Pi的值上有更高的精度,相同的代码将适用于小数点后超过15个数字的数字。数学库仅显示小数点后15个数字,这就是我设置该条件的原因。请告诉我是否知道如何获得更高精度的Pi,谢谢! - SJ44

1
您的解决方案似乎循环了错误的内容:
for number_of_places in fraser:

对于9个位置,这将变成类似以下内容:
for "9" in "3.141592653589793":

这个循环会循环三次,每次都会找到字符串中的一个"9"。我们可以修复你的代码:

from math import pi

fraser = str(pi)

length_of_pi = []

number_of_places = int(raw_input("Enter the number of decimal places you want: "))

for places in range(number_of_places + 1):  # +1 for decimal point
    length_of_pi.append(str(fraser[places]))

print "".join(length_of_pi)

但是这仍然限制了n小于len(str(math.pi)),在Python 2中小于15。对于一个严肃的n,它会崩溃:

> python test.py
Enter the number of decimal places you want to see: 100
Traceback (most recent call last):
  File "test.py", line 10, in <module>
    length_of_pi.append(str(fraser[places]))
IndexError: string index out of range
> 

要做得更好,我们必须自己计算PI——使用级数评估是一种方法:
# Rewrite of Henrik Johansson's (Henrik.Johansson@Nexus.Comm.SE)
# pi.c example from his bignum package for Python 3
#
# Terms based on Gauss' refinement of Machin's formula:
#
# arctan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + ...

from decimal import Decimal, getcontext

TERMS = [(12, 18), (8, 57), (-5, 239)]  # ala Gauss

def arctan(talj, kvot):

    """Compute arctangent using a series approximation"""

    summation = 0

    talj *= product

    qfactor = 1

    while talj:
        talj //= kvot
        summation += (talj // qfactor)
        qfactor += 2

    return summation

number_of_places = int(input("Enter the number of decimal places you want: "))
getcontext().prec = number_of_places
product = 10 ** number_of_places

result = 0

for multiplier, denominator in TERMS:
    denominator = Decimal(denominator)
    result += arctan(- denominator * multiplier, - (denominator ** 2))

result *= 4  # pi == atan(1) * 4
string = str(result)

# 3.14159265358979E+15 => 3.14159265358979
print(string[0:string.index("E")])

现在我们可以处理一个较大的n值:
> python3 test2.py
Enter the number of decimal places you want: 100
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067
> 

0

由于这个问题已经有了有用的答案,我只想分享一下我是如何创建一个与问题中非常相似的程序来实现同样的目的。

from math import pi
i = int(input("Enter the number of decimal places: "))
h = 0
b = list()
for x in str(pi):
    h += 1
    b.append(x)
    if h == i+2:
        break

h = ''.join(b)
print(h)

感谢阅读。


0
使用6位小数可以这样做
print (f"{math.pi:.6f}")

0
为什么不直接使用以下代码:
import numpy as np

def pidecimal(round):
    print(np.round(np.pi, round)) 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接