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 = []
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)
For whatever reason, it automatically prints pi without taking into account of any inputs. Any help would be great :)
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.
For example the mpmath package
from mpmath import mp
def a(n):
mp.dps=n+1
return(mp.pi)
Great answers! there are so many ways to achieve this. Check out this method I used below, it works any number of decimal places till infinity:
#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
Good luck Pal!
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
>
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')
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.
Why not just use:
import numpy as np
def pidecimal(round):
print(np.round(np.pi, round))
Related
I have a float numer
a = 1.263597
I hope get
b = 1.2635
But when I try
round (a,4)
then result is
1.2636
What should I do?
Try math.floor with this small modification -
import math
def floor_rounded(n,d):
return math.floor(n*10**d)/10**d
n = 1.263597
d = 4
output = floor_rounded(n,d)
print(output)
1.2635
For your example, you can just do math.floor(1.263597 * 10000)/10000
EDIT: Based on the valid comment by #Mark, here is another way of solving this, but this time forcing the custom rounding using string operations.
#EDIT: Alternate approach, based on the comment by Mark Dickinson
def string_rounded(n,d):
i,j = str(n).split('.')
return float(i+'.'+j[:d])
n = 8.04
d = 2
output = string_rounded(n,d)
output
8.04
Plain Python without importing any libraries (even not standard libraries):
def round_down(number, ndigits=None):
if ndigits is None or ndigits == 0:
# Return an integer if ndigits is 0
return int(number)
else:
return int(number * 10**ndigits) / 10**ndigits
a = 1.263597
b = round_down(a, 4)
print(b)
1.2635
Note that this function rounds towards zero, i.e. it rounds down positive floats and rounds up negative floats.
def round_down(number, ndigits=0):
return round(number-0.5/pow(10, ndigits), ndigits)
Run:
round_down(1.263597, 4)
>> 1.2635
I usually use
x = round(x, 3)
to round a number to the precision of 3 digits. Now I have this array:
[-1.10882605e-04 -2.01874994e-05 3.24209095e-05 -1.56917988e-05
-4.61406358e-05 1.99080610e-05 7.04079594e-05 2.64600122e-05
-3.53022316e-05 1.50542793e-05]
And using the same code just flattens everything down to 0. What I would like to have though is a function that gives me the most significant 3 digits rounded like it usually works for numbers larger than 1. Like this:
special_round(0.00034567, 3)
=
0.000346
Any idea how this could be done? Thanks!
Here is a solution that figures out the order of magnitude and does an elment wise rounding.
Note that this will only work correctly for values < 1 and > -1, which I guess is a valid assumption regarding your example data.
import numpy as np
a = np.array([-1.10882605e-04, -2.01874994e-05, 3.24209095e-05, -1.56917988e-05,
-4.61406358e-05, 1.99080610e-05, 7.04079594e-05 , 2.64600122e-05,
-3.53022316e-05 , 1.50542793e-05])
def special_round(vec):
exponents = np.floor(np.log10(np.abs(vec))).astype(int)
return np.stack([np.round(v, decimals=-e+3) for v, e in zip(vec, exponents)])
b = special_round(a)
>>> array([-1.109e-04, -2.019e-05, 3.242e-05, -1.569e-05, -4.614e-05,
1.991e-05, 7.041e-05, 2.646e-05, -3.530e-05, 1.505e-05])
Problem is, numbers you provided are starting to be so small that you are approaching limit of floating point precision, thus some artifacts show up seemingly for no reason.
def special_round(number, precision):
negative = number < 0
number = abs(number)
i = 0
while number <= 1 or number >= 10:
if number <= 1:
i += 1
number *= 10
else:
i += -1
number /= 10
rounded = round(number, precision)
if negative:
rounded = -rounded
return rounded * (10 ** -i)
Output:
[-0.0001109, -2.019e-05, 3.2420000000000005e-05, -1.569e-05, -4.614e-05, 1.9910000000000004e-05, 7.041000000000001e-05, 2.646e-05, -3.5300000000000004e-05, 1.505e-05]
You can do so by creating a specific function using the math package:
from math import log10 , floor
import numpy as np
def round_it(x, sig):
return round(x, sig-int(floor(log10(abs(x))))-1)
a = np.array([-1.10882605e-04, -2.01874994e-05, 3.24209095e-05, -1.56917988e-05,
-4.61406358e-05, 1.99080610e-05, 7.04079594e-05, 2.64600122e-05,
-3.53022316e-05, 1.50542793e-05])
round_it_np = np.vectorize(round_it) # vectorize the function to apply on numpy array
round_it_np(a, 3) # 3 is rounding with 3 significant digits
This will result in
array([-1.11e-04, -2.02e-05, 3.24e-05, -1.57e-05, -4.61e-05, 1.99e-05,
7.04e-05, 2.65e-05, -3.53e-05, 1.51e-05])
Here is a solution:
from math import log10, ceil
def special_round(x, n) :
lx = log10(abs(x))
if lx >= 0 : return round(x, n)
return round(x, n-ceil(lx))
for x in [10.23456, 1.23456, 0.23456, 0.023456, 0.0023456] :
print (x, special_round(x, 3))
print (-x, special_round(-x, 3))
Output:
10.23456 10.235
-10.23456 -10.235
1.23456 1.235
-1.23456 -1.235
0.23456 0.235
-0.23456 -0.235
0.023456 0.0235
-0.023456 -0.0235
0.0023456 0.00235
-0.0023456 -0.00235
You can use the common logarithm (provided by the built-in math module) to calculate the position of the first significant digit in your number (with 2 representing the hundreds, 1 representing the tens, 0 representing the ones, -1 representing the 0.x, -2 representing the 0.0x and so on...). Knowing the position of the first significant digit, you can use it to properly round the number.
import math
def special_round(n, significant_digits=0):
first_significant_digit = math.ceil((math.log10(abs(n))))
round_digits = significant_digits - first_significant_digit
return round(n, round_digits)
>>> special_round(0.00034567, 3)
>>> 0.000346
I need help with question 3 found in the link below
http://courses.cse.tamu.edu/davidkebo/csce-110/labs/lab_2.pdf
p = 15000
r = float(input("Enter interest rate (in percentage): "))
n = float(input("Enter loan period (in years): "))
c = p(1+r/100)**n
print()
print(f" At {r}% interest, you need to pay ${c} after {n} years")
I don't know why it's telling me that i have an uncallable 'int' or how i'd get the payoff to be rounded to 2 decimal points
This is because of c = p(1+r/100)**n
Anything with parentheses after it will be regarded as a function call in Python (p(...) in your case). You have to explicity give it a multiplication operator. Because p is an integer equal to 15000, you are trying to call an int... hence the error.
Change it to:
c = p * (1 + r / 100) ** n
In most programming languages you must explicitly put the multiplication operator when you want to do multiplication: p*(1+r/100)**n.
c = p * (1+r/100)**n
How can I take a float variable, and control how far out the float goes without round()? For example.
w = float(1.678)
I want to take x and make the following variables out of it.
x = 1.67
y = 1.6
z = 1
If I use the respective round methods:
x = round(w, 2) # With round I get 1.68
y = round(y, 1) # With round I get 1.7
z = round(z, 0) # With round I get 2.0
It's going to round and alter the numbers to the point where there no use to me. I understand this is the point of round and its working properly. How would I go about getting the information that I need in the x,y,z variables and still be able to use them in other equations in a float format?
You can do:
def truncate(f, n):
return math.floor(f * 10 ** n) / 10 ** n
testing:
>>> f=1.923328437452
>>> [truncate(f, n) for n in range(7)]
[1.0, 1.9, 1.92, 1.923, 1.9233, 1.92332, 1.923328]
A super simple solution is to use strings
x = float (str (w)[:-1])
y = float (str (w)[:-2])
z = float (str (w)[:-3])
Any of the floating point library solutions would require you dodge some rounding, and using floor/powers of 10 to pick out the decimals can get a little hairy by comparison to the above.
Integers are faster to manipulate than floats/doubles which are faster than strings. In this case, I tried to get time with both approach :
timeit.timeit(stmt = "float(str(math.pi)[:12])", setup = "import math", number = 1000000)
~1.1929605630000424
for :
timeit.timeit(stmt = "math.floor(math.pi * 10 ** 10) / 10 ** 10", setup = "import math", number = 1000000)
~0.3455968870000561
So it's safe to use math.floor rather than string operation on it.
If you just need to control the precision in format
pi = 3.14159265
format(pi, '.3f') #print 3.142 # 3 precision after the decimal point
format(pi, '.1f') #print 3.1
format(pi, '.10f') #print 3.1415926500, more precision than the original
If you need to control the precision in floating point arithmetic
import decimal
decimal.getcontext().prec=4 #4 precision in total
pi = decimal.Decimal(3.14159265)
pi**2 #print Decimal('9.870') whereas '3.142 squared' would be off
--edit--
Without "rounding", thus truncating the number
import decimal
from decimal import ROUND_DOWN
decimal.getcontext().prec=4
pi*1 #print Decimal('3.142')
decimal.getcontext().rounding = ROUND_DOWN
pi*1 #print Decimal('3.141')
I think the easiest answer is :
from math import trunc
w = 1.678
x = trunc(w * 100) / 100
y = trunc(w * 10) / 10
z = trunc(w)
also this:
>>> f = 1.678
>>> n = 2
>>> int(f * 10 ** n) / 10 ** n
1.67
Easiest way to get integer:
series_col.round(2).apply(lambda x: float(str(x).split(".",1)[0]))
def pi():
prompt=">>> "
print "\nWARNING: Pi may take some time to be calculated and may not always be correct beyond 100 digits."
print "\nShow Pi to what digit?"
n=raw_input(prompt)
from decimal import Decimal, localcontext
with localcontext() as ctx:
ctx.prec = 10000
pi = Decimal(0)
for k in range(350):
pi += (Decimal(4)/(Decimal(8)*k+1) - Decimal(2)/(Decimal(8)*k+4) - Decimal(1)/(Decimal(8)*k+5) - Decimal(1)/(Decimal(8)*k+6)) / Decimal(16)**k
print pi[:int(n)]
pi()
Traceback (most recent call last):
File "/Users/patrickcook/Documents/Pi", line 13, in <module>
pi()
File "/Users/patrickcook/Documents/Pi", line 12, in pi
print pi[:int(n)]
TypeError: 'Decimal' object has no attribute '__getitem__'
If you'd like a faster pi algorithm, try this one. I've never used the Decimal module before; I normally use mpmath for arbitrary precision calculations, which comes with lots of functions, and built-in "constants" for pi and e. But I guess Decimal is handy because it's a standard module.
''' The Salamin / Brent / Gauss Arithmetic-Geometric Mean pi formula.
Let A[0] = 1, B[0] = 1/Sqrt(2)
Then iterate from 1 to 'n'.
A[n] = (A[n-1] + B[n-1])/2
B[n] = Sqrt(A[n-1]*B[n-1])
C[n] = (A[n-1]-B[n-1])/2
PI[n] = 4A[n+1]^2 / (1-(Sum (for j=1 to n; 2^(j+1))*C[j]^2))
See http://stackoverflow.com/q/26477866/4014959
Written by PM 2Ring 2008.10.19
Converted to use Decimal 2014.10.21
Converted to Python 3 2018.07.17
'''
import sys
from decimal import Decimal as D, getcontext, ROUND_DOWN
def AGM_pi(m):
a, b = D(1), D(2).sqrt() / 2
s, k = D(0), D(4)
for i in range(m):
c = (a - b) / 2
a, b = (a + b) / 2, (a * b).sqrt()
s += k * c * c
#In case we want to see intermediate results
#if False:
#pi = 4 * a * a / (1 - s)
#print("%2d:\n%s\n" % (i, pi))
k *= 2
return 4 * a * a / (1 - s)
def main():
prec = int(sys.argv[1]) if len(sys.argv) > 1 else 50
#Add 1 for the digit before the decimal point,
#plus a few more to compensate for rounding errors.
#delta == 7 handles the Feynman point, which has six 9s followed by an 8
delta = 3
prec += 1 + delta
ctx = getcontext()
ctx.prec = prec
#The precision of the AGM value doubles on every loop
pi = AGM_pi(prec.bit_length())
#Round down so all printed digits are (usually) correct
ctx.rounding = ROUND_DOWN
ctx.prec -= delta
print("pi ~=\n%s" % +pi)
if __name__ == '__main__':
main()
You are trying to treat pi as an array, when it is a Decimal. I think you are looking for quantize:https://docs.python.org/2/library/decimal.html
I got bored with how long the process it was taking (that 350-iteration loop is a killer), but the answer seems plain. A Decimal object is not subscriptable the way you have it.
You probably want to turn it into a string first and then process that to get the digits:
print str(pi)[:int(n)+1] # ignore decimal point in digit count.
You should also keep in mind that this truncates the value rather than rounding it. For example, with PI starting out as:
3.141592653589
(about as much as I can remember off the top of my head), truncating the string at five significant digits will give you 3.1415 rather than the more correct 3.1416.
A Decimal object can't be sliced to get the individual digits. However a string can, so convert it to a string first.
print str(pi)[:int(n)]
You may need to adjust n for the decimal point and desired digit range.