I'm just starting to get into learning Python (Sorry, don't claim homework on this one, because it's not). Just to give myself some meaningful exercises to do to get better with the syntax and features, I've been following this URL: http://www.cs.washington.edu/homes/stepp/bridge/2007/exercises.html
This particular 'Overflow' issue I'm receiving with some floating point calculations is just mystifying me.
This is the error message I get:
Traceback (most recent call last):
File "./lab0102.py", line 28, in <module>
payment = PMT(r, n, P)
File "./lab0102.py", line 19, in PMT
return round(P * ((r *((1+r)**num_pmts)) / ((1+r)**num_pmts)))
OverflowError: (34, 'Numerical result out of range')
Here's my code:
import math
#from decimal import Decimal
def PMT(r, n, P):
rate = (r/100)/12
print "rate:", rate
num_pmts = n*12
payment = P * ((r *((1+r)**num_pmts)) / ((1+r)**num_pmts))
return payment
print "This program computes monthly loan payments."
P = input("Loan Amount? ")
n = input("Number of Years? ")
r = input("Interest Rate? ")
payment = PMT(r, n, P)
print "You payment is", payment
I've done everything by trying to typecast input, to use some of the wrapper operations to round or specify decimal point precision. I've even used the Decimal module to try and print out the decimal in string format to see where my logic flaw is.
Any takers on this one to educate me in the realm of floating point calculations in Python?
input() only gives you a float if it actually sees something that looks like a float; if it looks like an integer then you will get an integer. Use float(raw_input()) instead.
Now, as to the overflow.
Older versions of Python did not promote int to long automatically, meaning that the maximum integer you can have is signed 32- or 64-bit; any higher than that results in an overflow. Since you have integers in your expression (see above), you can potentially breach the maximum value for the type, resulting in the exception you're seeing.
Related
Here is my program :
r = float(input())
for i in range (1,6):
L = r-i
k = L//2
if isinstance(k, int):
print(L, r-L)
else :
print("IDK !")
When i plug in 17/6 this is the error that i get:
Traceback (most recent call last):
File "python", line 1, in <module>
ValueError: could not convert string to float: '17/6'
Thanks for helping me !
First off, you need to reformat your code so that it's readable for other people. But to answer your question, it's because "17/6" comes in as a string value. Converting a string to a float will convert actual numbers into a float. Numbers in Python are represented as decimals, not fractions, so 17/6 is "17 divided by 6" and not "17 over six". You would need to find a way to parse that as an operation to produce a float instead of trying to convert it directly to a float.
EDIT: To clarify, I understand that the fraction 17/6 and the results of dividing 17/6 are mathematically equivalent. That does not mean that python treats them as equivalen representation because fractions are not a native data type. If you print 17/6, it's not showing you a representation of 17/6. It's printing the result of 17.truediv(6).
I don't quite understand what your trying to do but if you want Python to evaluate your input say 17/6 as if you where to have input the result of 17/6 as a float (2.833333333333333) replace
r = float(input())
with
r = float(eval(input()))
eval will evaluate the input string ("17/6") as 17.truediv(6) which is a float and then save that to r
also in my tests the line
if isinstance(k, int):
always evaluates to false as // doesn't change type to int and even if id did it would do so consistently
PROBLEM STATEMENT: Write a Python script to determine the smallest positive double number in Python.
Your code should produce a variable called smallest_num which is the smallest double number in Python.
Your script should determine this value in a systematic manner. You may NOT simply call a built-in function that returns this value or access a built-in variable that contains this information. This includes np.finfo() and other built-in functions or variables.
The setup code gives the following variables:
Your code snippet should define the following variables:
Name Type Description
smallest_num floating point The smallest number possible in Python
Attempted Solution
import numpy as np
import math
def machineEpsilon(func=float):
machine_epsilon = func(1)
while func(1)+func(machine_epsilon) != func(1):
machine_epsilon_last = machine_epsilon
machine_epsilon = func(machine_epsilon) / func(2)
return machine_epsilon_last
sum_f = machineEpsilon(np.float64)
smallest_sum = float(sum_f)
print(isinstance(smallest_sum, float))
print(smallest_sum)
Output
True
2.220446049250313e-16
However, I am unable to get the correct answer. As the true smallest number is much smaller than the printed value. I know this number will be underflow to zero and I might want to do some comparison here. But i am a bit stuck. Any thoughts?
Probably the most reasonable thing to do would be to directly compute the next double-precision float after 0.0:
smallest_num = np.nextafter(0, 1)
This does not simply call a built-in function that returns the smallest positive double-precision float, or access a variable pre-set to that value. However, people get weird when they see function call syntax in problems like this, so it risks being marked incorrect anyway.
Taking advantage of how IEEE754 floating-point representation and rounding works, we can start with 1.0 and divide by 2 until the next division would underflow:
smallest_num = 1.0
while smallest_num / 2:
smallest_num /= 2
I'd like to calculate the square root of a number bigger than 10^2000 in Python. If I treat this number like a normal integer, I will always get this result back:
Traceback (most recent call last):
File "...", line 3, in <module>
print( q*(0.5) )
OverflowError: int too large to convert to float
How do I fix this? Or does a possibilty other than using Python exist to calculate this square root?
Just use the decimal module:
>>> from decimal import *
>>> Decimal(10**2000).sqrt()
Decimal('1.000000000000000000000000000E+1000')
>>> Decimal(10**200000).sqrt()
Decimal('1.000000000000000000000000000E+100000')
>>> Decimal(15**35315).sqrt()
Decimal('6.782765081358674922386659760E+20766')
You can also use the gmpy2 library.
>>> import gmpy2
>>> n = gmpy2.mpz(99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999982920000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000726067)
>>> gmpy2.get_context().precision=2048
>>> x = gmpy2.sqrt(n)
Useful links:
Decimal - Python Documentation
The usual square root methods convert the parameter to a float value before doing the calculation. As you saw, this does not work well with very large integers.
So use a function that is designed to work on arbitrarily large integers. Here is one, guaranteed to return correct integer part of the square root of any positive integer. This function drops the fractional part of the result, which may or may not be what you want. Since this function uses iteration it is also slower than the built-in square root routines. The Decimal module works on larger integers than the built-in routines but the precision of the values must be defined in advance so it does not work on arbitrarily large values.
import math
_1_50 = 1 << 50 # 2**50 == 1,125,899,906,842,624
def isqrt(x):
"""Return the integer part of the square root of x, even for very
large integer values."""
if x < 0:
raise ValueError('square root not defined for negative numbers')
if x < _1_50:
return int(math.sqrt(x)) # use math's sqrt() for small parameters
n = int(x)
if n <= 1:
return n # handle sqrt(0)==0, sqrt(1)==1
# Make a high initial estimate of the result (a little lower is slower!!!)
r = 1 << ((n.bit_length() + 1) >> 1)
while True:
newr = (r + n // r) >> 1 # next estimate by Newton-Raphson
if newr >= r:
return r
r = newr
When using sqrt from the library math, before it proceeds to square root it, it will convert the value to a float.
If we manually try to convert the 10**2000 to a float, it also triggers an error
>>> float(10**2000)
---------------------------------------------------------------------------
OverflowError Traceback (most recent call last)
<ipython-input-14-6ac81f63106d> in <module>
----> 1 math.sqrt(10**2000)
OverflowError: int too large to convert to float
If we were speaking of a big number, but with the square equals or less than 308, the Decimal module would do the work as follows
>>> from decimal import Decimal
>>> Decimal(math.sqrt(10**308))
Decimal('10000000000000000369475456880582265409809179829842688451922778552150543659347219597216513109705408327446511753687232667314337003349573404171046192448274432')
However, as the number is way square is way bigger than 308, in this case, 2000, one would have to do as follows
>>> from decimal import Decimal
>>> Decimal(10**2000).sqrt()
Decimal('1.000000000000000000000000000E+1000')
Let's see the output if one tries to convert the Decimal(10**2000) to float
>>> float(Decimal(10**2000))
inf
One might also use the decimal module when working with factorials, as they tend to get large really fast.
I tried to make a short program that works out the famous Drake equation. I got it to accept integer inputs, decimal inputs, and fractional inputs. However, I get this error when the program attempts to multiply them (right after I input all necessary values the error happens):
Traceback (most recent call last)
File "C:/Users/Family/Desktop/Programming/Python Files/1/DrakeEquation1.py", line 24, in <module>
calc() #cal calc to execute it
File "C:/Users/Family/Desktop/Programming/Python Files/1/DrakeEquation1.py", line 17, in calc
calc = r*fp*ne*fl*fi*fc*l
TypeError: can't multiply sequence by non-int of type 'str'
My code is as follows:
def intro():
print('This program will evaluate the Drake equation with your values')
def calc():
print('What is the average rate of star formation in the galaxy?')
r = input()
print('What fraction the stars have planets?')
fp = input()
ne = int(input('What is the average number of life supporting planets (per star)?'))
print('What fraction of these panets actually develop life')
fl = input()
print('What fraction of them will develop intelligent life')
fi = input()
print('What fraction of these civilizations have developed detectable technology?')
fc = input()
l = int(input('How long will these civilizations release detectable signals?'))
calc = r*fp*ne*fl*fi*fc*l
print('My estimate of the number of detectable civilizations is ' + calc + ' .')
if __name__=="__main__":
intro() #cal intro to execute it
calc() #cal calc to execute it
What do I need to change in order to fix this problem?
You need to convert your input values to floats.
r = float(input())
(Note: in Python versions less than 3, use raw_input instead of input.)
And so on for the other variables. Otherwise you're attempting to multiply a string by a string.
Edit: as others have pointed out, calc additionally cannot be concatenated to the surrounding strings using the + operator. Use string substitution for that:
print('My estimate of the number of detectable civilizations is %s.' % calc)
Contrary to the answers asserting that the problem's with not casting the output of input to the correct type. The real problem is
Not properly validating the input to the program, and
Trying to concatenate a str with a number on this line:
print('My estimate of th..." + calc + ' .')
Your program runs fine for me given integers, floats and fractional values as input. Given '1' and '1' (quoted) as the first two inputs, it returns the error you're seeing.
You have converted some values into appropriate types for arithmetic but not the others. The real values should be passed to float() and the ratios should be parsed and computed (or use the Fraction type, or force your user to input a real). An example of the latter is posted below:
print('What is the average rate of star formation in the galaxy?')
r = float(input())
print('What fraction the stars have planets?')
fp = float(input())
ne = int(input('What is the average number of life supporting planets (per star)?'))
print('What fraction of these panets actually develop life')
fl = float(input())
input([prompt]) -> value
Equivalent to eval(raw_input(prompt)).
So, I suggest you to use raw_input to avoid potential errors.
I'm trying to compute this:
from scipy import *
3600**3400 * (exp(-3600)) / factorial(3400)
the error: unsupported long and float
Try using logarithms instead of working with the numbers directly. Since none of your operations are addition or subtraction, you could do the whole thing in logarithm form and convert back at the end.
Computing with numbers of such magnitude, you just can't use ordinary 64-bit-or-so floats, which is what Python's core runtime supports. Consider gmpy (do not get the sourceforge version, it's aeons out of date) -- with that, math, and some care...:
>>> e = gmpy.mpf(math.exp(1))
>>> gmpy.mpz(3600)**3400 * (e**(-3600)) / gmpy.fac(3400)
mpf('2.37929475533825366213e-5')
(I'm biased about gmpy, of course, since I originated and still participate in that project, but I'd never make strong claims about its floating point abilities... I've been using it mostly for integer stuff... still, it does make this computation possible!-).
You could try using the Decimal object. Calculations will be slower but you won't have trouble with really small numbers.
from decimal import Decimal
I don't know how Decimal interacts with the scipy module, however.
This numpy discussion might be relevant.
Well the error is coming about because you are trying to multiply
3600**3400
which is a long with
exp(-3600)
which is a float.
But regardless, the error you are receiving is disguising the true problem. It seems exp(-3600) is too big a number to fit in a float anyway. The python math library is fickle with large numbers, at best.
exp(-3600) is too smale, factorial(3400) is too large:
In [1]: from scipy import exp
In [2]: exp(-3600)
Out[2]: 0.0
In [3]: from scipy import factorial
In [4]: factorial(3400)
Out[4]: array(1.#INF)
What about calculate it step by step as a workaround(and it makes sense
to check the smallest and biggest intermediate result):
from math import exp
output = 1
smallest = 1e100
biggest = 0
for i,j in izip(xrange(1, 1701), xrange(3400, 1699, -1)):
output = output * 3600 * exp(-3600/3400) / i
output = output * 3600 * exp(-3600/3400) / j
smallest = min(smallest, output)
biggest = max(biggest, output)
print "output: ", output
print "smallest: ", smallest
print "biggest: ", biggest
output is:
output: 2.37929475534e-005
smallest: 2.37929475534e-005
biggest: 1.28724174494e+214