One of the challenges on w3resources is to print pi to \'n\' decimal places. Here is my code:
from math import pi
fraser = str(pi)
length_of_pi = []
numbe
Your solution appears to be looping over the wrong thing:
for number_of_places in fraser:
For 9 places, this turns out be something like:
for "9" in "3.141592653589793":
Which loops three times, one for each "9" found in the string. We can fix your code:
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)
But this still limits n
to be less than the len(str(math.pi))
, less than 15 in Python 2. Given a serious n
, it breaks:
> 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
>
To do better, we have to calculate PI ourselves -- using a series evaluation is one approach:
# 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")])
Now we can take on a large value of n
:
> python3 test2.py
Enter the number of decimal places you want: 100
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067
>
Why not just use:
import numpy as np
def pidecimal(round):
print(np.round(np.pi, round))
The proposed solutions using np.pi
, math.pi
, etc only only work to double precision (~14 digits), to get higher precision you need to use multi-precision, for example the mpmath package
>>> from mpmath import mp
>>> mp.dps = 20 # set number of digits
>>> print(mp.pi)
3.1415926535897932385
Using np.pi
gives the wrong result
>>> format(np.pi, '.20f')
3.14159265358979311600
Compare to the true value:
3.14159265358979323846264338327...
Why not just format
using number_of_places
:
''.format(pi)
>>> format(pi, '.4f')
'3.1416'
>>> format(pi, '.14f')
'3.14159265358979'
And more generally:
>>> number_of_places = 6
>>> '{:.{}f}'.format(pi, number_of_places)
'3.141593'
In your original approach, I guess you're trying to pick a number of digits using number_of_places
as the control variable of the loop, which is quite hacky but does not work in your case because the initial number_of_digits
entered by the user is never used. It is instead being replaced by the iteratee values from the pi
string.
As this question already has useful answers, I would just like to share how i created a program for the same purpose, which is very similar to the one in the question.
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)
Thanks for Reading.
This is what I did, really elementary but works (max 15 decimal places):
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')