I'm new to python (and coding too) so I'm following a tutorial book. I'm try to calculate pi to a set number of decimal places using the Chudnovsky algorithm from code outlined in the book; however, when I execute the code I get an error saying:
> File "C:/Users/user/Documents/Python/Scripts/Tutorials/Calculating
> pi.py", line 15, in calc
> t = (Decimal(-1)**k)*(math.factorial(Decimal(6)*k))*(13591409 + 545140134*k) TypeError: 'decimal.Decimal' object cannot be interpreted
> as an integer
Here is the original code:
from decimal import Decimal, getcontext
import math
numberofdigits = int(input("please enter the number of decimal places to calculate Pi to: "))
getcontext().prec = numberofdigits
def calc(n):
t = Decimal(0)
pi = Decimal(0)
deno = Decimal(0)
k = 0
for k in range(n):
t = (Decimal(-1)**k)*(math.factorial(Decimal(6)*k))*(13591409+545140134*k)
deno = math.factorial(3*k)*(math.factorial(k)**Decimal(3))*(640320**(3*k))
pi += Decimal(t)/Decimal(deno)
pi = pi * Decimal(12)/Decimal(640320**Decimal(1.5))
pi = 1/pi
return str(pi)
print (calc(1))
Where am I going wrong here? I have triple checked for spelling errors etc. but have not found anything but don't really understand what the decimal.decimal type error means.
EDIT:
I've been playing around with it and found that if I separate the terms of the numerator I get:
def calc(n):
t = Decimal(0)
pi = Decimal(0)
deno = Decimal(0)
k = 0 for k in range(n):
u=(Decimal(-1)**k)
x=(Decimal(6)*k)
v=math.factorial(x)
w=(13591409+545140134*k)
t = u*v*w
deno = math.factorial(3*k)*(math.factorial(k)**Decimal(3))*(640320**(3*k))
This gives me the following error:
line 17, in calc v=math.factorial(x) TypeError: 'decimal.Decimal' object cannot be interpreted as an integer
Cheers
The problem seems to be that the math.factorial() function accepts only integers or floats with integral values, but does not support Decimal objects:
print(math.factorial(6))
# 720
print(math.factorial(6.0))
# 720
print(math.factorial(Decimal(6)))
# TypeError: 'decimal.Decimal' object cannot be interpreted as an integer
Changing the value passed to math.factorial() on line 15 should fix the error:
t = (Decimal(-1)**k) * (math.factorial(6 * k)) * (13591409+545140134 * k)
Interestingly, your original code works fine using Python 3.6.9, but fails in Python 3.8.2, because this behavior was introduced in Python 3.8 (yes, this is the intended behavior).
The logic behind this behavior can be fully understood by reading this discussion about dropping support for Decimal objects in math.factorial():
Issue 33083: math.factorial accepts non-integral Decimal instances
Related
from fractions import Fraction
from functools import reduce
def product(fracs): ## fracs is a list of Fraction objects from the subsequent function call
t = Fractions(reduce(lambda x,y: x.numerator * y.numerator,fracs), reduce(lambda x,y: x.denominator * y.denominator, fracs))
return t.numerator, t.denominator
if __name__ == '__main__':
fracs = []
for _ in range(int(input())):
fracs.append(Fraction(*map(int, input().split())))
result = product(fracs)
print(*result)
I'm trying to multiply a series of fractions together using Python3 functool's Fraction function. The problem i have is with the denominator perimeter for the t variable in the product(fracs) function. Upon testing with the following test case:
3
1 2
3 4
10 6
5 1
The output was 5 1. The numerator seem to work fine but broke down for the denominator. I am aware and have found alternative solutions to my problem however i am hoping to get this mystery solved. I've ran it through python tutor but i couldn't decipher the code's behavior.
I think it's how you are using reduce. The first time it's called you are passing two Fraction objects:
Fraction(1,2).denominator * Fraction(3,4).denominator
which returns 8 and is what you expect. However, the reduce function is not making this 8 a fraction so the next call to reduce looks like this:
8.denominator * Fraction(10,6).denominator
Which is 6 not the expected 48. This problem doesn't exist for the numerator because for an Int X:
X = X.numerator
Therefore you get 30 in the numerator and 6 in the denominator which reduces to 5.
I'm not familiar with the Fraction class but it seems like you might be reinventing the wheel a bit.
I suspect you can just multiply the fraction objects and it's multiplication operator is overloaded:
def product(fracs):
return reduce(lambda x,y: x * y, fracs)
I am writing a function to evaluate and return a non linear system of equations, and give the jacobian. I then plan to call the function in a while loop to use the newton method to solve the system of equations.
I used the numpy package and read over its documentation, tried to limit the number of iterations, changed the dtype in the array and searched online to see if someone else had a similar problem.
This function is meant to solve a neoclassical growth model (a problem in macroeconomics) in finite time , T. The set of equations include T euler equations, T constraints, and one terminal condition. Thus the result should be an array of length 2T+1 containing the values of the equations, and a (2T+1)x(2T+1) jacobian matrix.
When I try to run the function for small array (arrays of length 1, and 3) it works perfectly. As soon as I try an array of length 5 or more, I start encountering RuntimeWarnings.
import numpy as np
def solver(args, params):
b,s,a,d = params[0], params[1], params[2], params[3]
guess = np.copy(args)
#Euler
euler = guess[:len(guess)//2]**(-sigma) - beta*guess[1:len(guess)//2+1]**(-sigma)*(1-delta+alpha*guess[len(guess)//2+1:]**(alpha-1))
#Budget Constraint
kzero_to_T = np.concatenate(([k0], guess[len(guess)//2+1:]))
bc_t = guess[:len(guess)//2] + guess[len(guess)//2+1:] - kzero_to_T[:-1]**alpha - (1-delta)*kzero_to_T[:-1]
bc_f = guess[len(guess)//2] -kzero_to_T[-1]**alpha - kzero_to_T[-1]*(1-delta)
bc = np.hstack((bc_t, bc_f))
Evals = np.concatenate((euler, bc))
# top half of the jacobian
jac_dot_5 = np.zeros((len(args)//2, len(args)))
for t in range(len(args)//2):
for i in range(len(args)):
if t == i and len(args)//2+(i+1)<=len(args):
jac_dot_5[t][t] = -sigma*args[t]**(-sigma-1)
jac_dot_5[t][t+1] = sigma*beta*args[t+1]*(1-delta+alpha*args[len(args)//2+(t+1)]**(alpha-1))
jac_dot_5[t][len(args)//2+(t+1)] = beta*args[t+1]**(-sigma)*alpha*(alpha-1)*args[len(args)//2+(t+1)]
# bottom half of the jacobian
jac_dot_1 = np.zeros((len(args)//2, len(args)))
for u in range(len(args)//2):
for v in range(len(args)):
if u==v and u>=1 and (len(args)//2 + u+1 < len(args)):
jac_dot_1[u][u] = 1
jac_dot_1[u][len(args)//2+(u)] = 1
jac_dot_1[u][len(args)//2+(u+1)] = -alpha*args[len(args)//2 + (u+1)]**(alpha-1) -(1-delta)
jac_dot_1[0][0] = 1
jac_dot_1[0][len(args)//2 +1] = 1
# last row of the jacobian
final_bc = np.zeros((1,len(args)))
final_bc[0][len(args)//2] = 1
final_bc[0][-1] = -alpha*args[-1]**(alpha-1) -(1-delta)
jac2Tn1 = np.concatenate((jac_dot_5, jac_dot_1, final_bc), axis=0)
point = coll.namedtuple('point', ['Output', 'Jacobian', 'Euler', 'BC'])
result = point(Output = Evals, Jacobian = jac2Tn1, Euler=euler, BC=bc )
return result
The code for implementing the algorithm:
p = (beta, sigma, alpha, delta)
for i in range(20):
k0 = np.linspace(2.49, 9.96, 20)[i]
vars0 = np.array([1,1,1,1,1], dtype=float)
vars1 = np.array([20,20,20,20,20], dtype=float)
Iter2= 0
while abs(solver(vars1,p).Output).max()>1e-8 and Iter2<300:
Iter2+=1
inv_jac1 = np.linalg.inv(solver(vars0,p).Jacobian)
vars1 = vars0 - inv_jac1#solver(vars0,p).Output
vars0=vars1
if Iter2 == 100:
break
I expect the output to be vars1 containing the updated values. The actual output is array([nan, nan, nan, nan, nan]). The way the function has been written, it should be able to give the output for inputs of arbitrary guesses of length 2T+1, where T is number of periods of time.
I get three error messages during the execution of the loop:
C:\Users\Peter\Anaconda3\lib\site-packages\ipykernel_launcher.py:19: RuntimeWarning: invalid value encountered in power
C:\Users\Peter\Anaconda3\lib\site-packages\ipykernel_launcher.py:23: RuntimeWarning: invalid value encountered in power
C:\Users\Peter\Anaconda3\lib\site-packages\ipykernel_launcher.py:41: RuntimeWarning: invalid value encountered in double_scalars
I tried to code my issue from scratch and I couldn't make it any shorter- I need both, the evaluations of the equations and the jacobian to implement the algorithm. From my testing it looks like at some point the equation results (the solver(vars0,p).Output entry) become nan, but I am not sure why that would happen, the array should get close to 0, per the condition abs(solver(vars1,p).Output).max()>1e-8 and then just break out of the loop.
I'm quite new at Python programming so forgive me if it seems like a stupid question. This is my code with the given results:
Code:
def Stopping_Voltage(Frequency, Phi):
x = (4.14E-15) * Frequency ##The value of (h/e) multiplied by frequency
y = Phi / (1.602E-19) ##The value of Phi/e
Energy = x * (1.602E-19)
print(Energy)
print(Phi)
print(x)
print(y)
String = 'No electron is emitted'
if Energy > Phi:
Voltage = x - y
return(Voltage)
else:
return(String)
Stopping_Voltage(10, (6.63228E-33))
Result:
6.632280000000001e-33
6.63228e-33
4.1400000000000005e-14
4.14e-14
6.310887241768095e-30
What we're asked to do is if the energy is less than or equal to phi, return the string but when testing it with the given variables, it should return the string but it is still giving me a quantitative result. I initially tried using "else" rather than "elif" but it still gave me the same thing (if that matters). When I printed the value for Energy and Phi, the energy value has a lot of zeroes after the decimal (with 1 following after all the zeroes). How do I fix this to give me the string?
Your code is fine! It does return the string, if Energy is <= Phi. It's just that your Energy in this particular example is really bigger than your Phi :) This is the scientific notation of a number, so e means 10^exponent like 2e-5 is equal to 2*10^-5. You can check it by adding print(Energy > Phi) which will print you either True or False e.g. before the if-else block.
I'm writing a very simple program that calculates how far an object has fallen due to gravity given how long it's been in the air.
(main.py)
# Importing falling_distance function
from a3_functions import falling_distance
# Doc-string
import a3_functions; print(a3_functions.falling_distance.__doc__)
# Input from user and formatted output
t = input('Enter the time (in secs): ')
print("The Object has fallen {:.2f} in {:d} seconds".format(falling_distance(t), t))
^^ Being the main module/class where the user puts in the amount of time. After that it references the program a3_functions.py which is essentially a library for various functions.
(a3_functions.py)
def falling_distance (t):
"""-------------------------------------------------------------------------
Purpose: Calculate and output falling distance (in metres) given time (in
seconds)
---------------------------------------------------------------------------
Preconditions:
t - time (int > 0)
g - gravitational constant
Postconditions:
returns:
d - distance (float > 0)
---------------------------------------------------------------------------
"""
t = int(t)
g = 9.8
d = (1/2)*g*t**2
return d
I know i can do it very simply in one program but can anyone tell me when d is being returned as 0?
In my opinion, i think it has something to do with the way eclipse is set up because it worked before. I worked on other programs, came back to this one and it broke. I feel like this is a simple problem that happens way too often and has an easy fix
You are using Python 2, not Python 3. They are often both installed on the same computer, and on most systems the default is 2 instead of 3. If you explicitly start it with python3 instead of just python, you should be able to get Python 3 if it’s installed.
Specifically, in Python 2, if you divide two integers, it converts the result to an integer, so 1/2 gives 0. This was changed to do floating-point division in Python 3.
Additionally, the input function in Python 2 is equivalent to eval(input(...)) in Python 3, so t is already an int. In Python 3, your format call doesn’t work because you can’t use {:d} on a string.
I'm entirely new to programming and I'm supposed to turn pseudocode into a Python algorithm for a class assignment. I've tested mine algorithm (if you can even call it that) a few too many times and keep coming up with error messages. Any suggestions or resources that might be able to help would be greatly appreciated!
Pseudocode Order:
Declare Real radius
Declare Real area
Display “ Enter value for radius : “
Input radius
Set area = 3.14 * radius * radius
Display Area
Attempted Code:
radius = 1.0
Area = 1.0
print(" Enter value for radius : ")
radius = input(" Enter value for radius : ")
Area = 3.14 * radius * radius
print(Area)
and the error:
TypeError: can't multiply sequence by non-int of type 'float'
input() returns a string, thus your TypeError. You tried to multiply a string by a float.
Updated Code here:
radius = 1.0
print("Enter value for radius : ")
radius = input()
print(type(radius))
Area = 3.14 * (float(radius) * float(radius))
print(Area)
Output:
Enter value for radius :
5
<class 'str'>
78.5
The best way to do this is:
import math
radius = input("Enter a radius: ")
area = math.pi * radius ** 2
print("The area is: " + str(area) + "cm squared.")
A few things happen here:
On the first line we import the math module, which contains a bunch of values (like π) and lots of methods (like tan). For more on modules, take a look here.
On the second line, we ask for the radius. Note that unlike lower level programming languages, we don't have to initialise it. Python figures out that it is an float (a decimal) by itself. EDIT: If you are using python 2, you do have to cast, just as Damien pointed out, by using radius = float(input("Enter an area: ))
On line three we set the area equal to πr^2. We call the math.pi value, which is very precise, then we multiply that by r ^ 2 (in python if we want to a to the power of b we write a ** b)
On line 4 we print the area as a String. Note that we have to cast the float area to be a string using the str() function. This is basically Java's easy way to print anything that isn't a string as a string (a collection of characters).
Hope that helps!
Well, I will add some explain to this:
radius = 1.0 #this is not mandatory, you can create the variable and assign the value in the same moment
area = 1.0
radius = float(input(" Enter value for radius : ")) #here is so important to convert the input into a float, that's the other error you had
area = 3.14 * radius * radius t isn't working
print(area)