Float Limit in Python - python

I was writing a program in python
import sys
def func(N, M):
if N == M:
return 0.00
else:
if M == 0:
return pow(2, N+1) - 2.00
else :
return 1.00 + (0.5)*func(N, M+1) + 0.5*func(N, 0)
def main(*args):
test_cases = int(raw_input())
while test_cases:
string = raw_input()
a = string.split(" ")
N = int(a[0])
M = int(a[1])
test_cases = test_cases -1
result = func(N, M)
print("%.2f" % round(result, 2))
if __name__ == '__main__':
sys.setrecursionlimit(1500)
sys.exit(main(*sys.argv))
It gives the same answer for N = 1000 ,M = 1 and N = 1000 , M = 2
On searching I found that limit of float expires over 10^400. My question is how to overcome it

Floats in Python are IEEE doubles: they are not unlimited precision. But if your computation only needs integers, then just use integers: they are unlimited precision. Unfortunately, I think your computation does not stay within the integers.
There are third-party packages built on GMP that provide arbitrary-precision floats: https://www.google.com/search?q=python%20gmp

I maintain one of the Python to GMP/MPFR libraries and I tested your function. After checking the results and looking at your function, I think your function remains entirely in the integers. The following function returns the same values:
def func(N, M):
if M == 0:
return 2**(N+1) - 2
elif N == M:
return 0
else:
return func(N, M+1)//2 + 2**N
The limiting factor with Python's builtin float is not the exponent range (roughly 10**308) but the precision (53 bits). You need around N bits of precision to distinguish between func(N,1) and func(N,2)

Consider using an arbitrary precision floating-point library, for example the bigfloat package, or mpmath.

Related

Errors in Directly vs Recursively Calculating a given Fibonacci Number

I was bored at work and was playing with some math and python coding, when I noticed the following:
Recursively (or if using a for loop) you simply add integers together to get a given Fibonacci number. However there is also a direct equation for calculating Fibonacci numbers, and for large n this equation will give answers that are, frankly, quite wrong with respect to the recursively calculated Fibonacci number.
I imagine this is due to rounding and floating point arithmetic ( sqrt(5) is irrational after all), and if so can anyone point me into a direction on how I could modify the fibo_calc_direct function to return a more accurate result?
Thanks!
def fib_calc_recur(n, ii = 0, jj = 1):
#n is the index of the nth fibonacci number, F_n, where F_0 = 0, F_1 = 1, ...
if n == 0: #use recursion
return ii
if n == 1:
return jj
else:
return(fib_calc_recur(n -1, jj, ii + jj))
def fib_calc_direct(n):
a = (1 + np.sqrt(5))/2
b = (1 - np.sqrt(5))/2
f = (1/np.sqrt(5)) * (a**n - b**n)
return(f)
You could make use of Decimal numbers, and set its precision depending on the magninute of n
Not your question, but I'd use an iterative version of the addition method. Here is a script that makes both calculations (naive addition, direct with Decimal) for values of n up to 4000:
def fib_calc_iter(n):
a, b = 0, 1
if n < 2:
return n
for _ in range(1, n):
a, b = b, a + b
return b
from decimal import Decimal, getcontext
def fib_calc_decimal(n):
getcontext().prec = n // 4 + 3 # Choose a precision good enough for this n
sqrt5 = Decimal(5).sqrt()
da = (1 + sqrt5) / 2
db = (1 - sqrt5) / 2
f = (da**n - db**n) / sqrt5
return int(f + Decimal(0.5)) # Round to nearest int
# Test it...
for n in range(1, 4000):
x = fib_calc_iter(n)
y = fib_calc_decimal(n)
if x != y:
print(f"Difference found for n={n}.\nNaive method={x}.\nDecimal method={y}")
break
else:
print("No differences found")

OverflowError: int too large to convert to float even with "Decimal" - Python

This question got already an answer on stackoverflow and the recommended solution was to use "Decimal" form the module math
But Decimal didn't work ->
from decimal import Decimal
import math
def pow_opt(x:int, n:int)-> int:
result = 1
while Decimal(math.pow(x,n)):
if (n%2 == 0):
x = x**2
n = n/2
else:
result = result*x
n = n-1
print(pow_opt(4,2))
And the following error is returned :
[click to see error]
You hardly need any Decimal for that. Your implementation is incorrect. When it has been corrected (see code below) it works with integers:
def pow_opt(x:int, n:int)-> int:
result = 1
while n:
if (n%2 == 0):
x = x**2
n = n/2
else:
result = result*x
n = n-1
return result

numpy precision with large numbers

I want to factorize a large number using Fermat's factorization method. This is how I implemented it:
import numpy as np
def fac(n):
x = np.ceil(np.sqrt(n))
y = x*x - n
while not np.sqrt(y).is_integer():
x += 1
y = x*x - n
return(x + np.sqrt(y), x - np.sqrt(y))
Using this method I want to factor N into its components. Note that N=p*q, where p and q are prime.
I chose the following values to compute N:
p = 34058934059834598495823984675767545695711020949846845989934523432842834738974239847294083409583495898523872347284789757987987387543533846141.0
q = 34058934059834598495823984675767545695711020949846845989934523432842834738974239847294083409583495898523872347284789757987987387543533845933.0
and defined N
N = p*q
Now I factor N:
r = fac(n)
However, the factorization seems to not be correct:
int(r[0])*int(r[1]) == N
It does work for smaller ints:
fac(65537)
Out[1]: (65537.0, 1.0)
I'm quite sure the reason is numerical precision at some point.
I tried calculating N in numpy using object types:
N = np.dot(np.array(p).astype(object), np.array(q).astype(object))
but it doesn't help. Still, the numpy requires a float for the sqrt function.
I also tried using the math library instead of numpy, this library seems to not require a float for its sqrt function, but ultimately running into precision issues as well.
Python int are multiple precision numbers. But numpy is a wrapper around C low level libraries to speed up operations. The downside is that it cannot handle those multi-precision numbers. Worse, if you try to use np.sqrt on them, they will be converted to floating point numbers (C double or numpy float64) what have a precision of about 15 decimal digits.
But as Python int type is already a multiprecision type, you could use math.sqrt to get an approximative value of the true square root, and then use Newton to find a closer value:
def isqrt(n):
x = int(math.sqrt(n))
old = None
while True:
d = (n - x * x) // (2 * x)
if d == 0: break
if d == 1: # infinite loop prevention
if old is None:
old = 1
else: break
x += d
return x
Using it, your fac function could become:
def fac(n):
x = isqrt(n)
if x*x < n: x += 1
y = x * x - n
while True:
z = isqrt(y)
if z*z == y: break
x += 1
y = x*x -n
return x+z, x-z
Demo:
p = 34058934059834598495823984675767545695711020949846845989934523432842834738974239847294083409583495898523872347284789757987987387543533846141
q = 34058934059834598495823984675767545695711020949846845989934523432842834738974239847294083409583495898523872347284789757987987387543533845933
N = p*q
print(fac(N) == (p,q))
prints as expected True

calculating factorial of large numbers in 0.5 second with python

I've been trying to find a super fast code that can calculate the factorial of a big number like 70000 in 0.5 second,My own code could do it in 10 seconds.I've searched everywhere, every code I find has memory error problem or is not as fast as I want. Can anyone help me with this?
enter code here
import math
num =int(raw_input())
usefrm=0
if len(str(num)) > 2:
if int(str(num)[-2]) % 2 == 0:
usefrm = 'even'
else:
usefrm = 'odd'
else:
if num % 2 == 0:
usefrm = 'even1'
else:
usefrm = 'odd1'
def picknumber(num):
s = str(math.factorial(num))
l = []
for n in s:
if int(n) != 0:
l.append(int(n))
return l[-1]
def picknumber1(num):
s = str(num)
l = []
for n in s:
if int(n) != 0:
l.append(int(n))
return l[-1]
if usefrm == 'even':
e=picknumber1(6*picknumber(int(num/5))*picknumber(int(str(num)[-1])))
if usefrm == 'odd':
e=picknumber1(4*picknumber(int(num/5))*picknumber(int(str(num)[-1])))
else:
e=picknumber1(math.factorial(num))
print e
For most practical use, the Stirling's approximation is very fast and quite accurate
import math
from decimal import Decimal
def fact(n):
d = Decimal(n)
return (Decimal(2 * math.pi) * d).sqrt() * (d / Decimal(math.e)) ** d
print(fact(70000))
1.176811014417743803074731978E+308759
Try to use the commutativity property of integer multiplication.
When multiplied numbers are long (they do not fit in a single word), the time necessary to perform the operation grows superlinearly with their length.
If you multiply the smallest (shortest in terms of memory representation) factors (and partial products) first, you may save a lot of time.
You may use math.factorial(). For example:
from math import factorial
factorial(7000)
with execution time of 20.5 msec for calculating the factorial of 7000:
python -m timeit -c "from math import factorial; factorial(7000)"
10 loops, best of 3: 20.5 msec per loop
If you don't want a perfect precision, you can use the Stirling's approximation
https://en.wikipedia.org/wiki/Stirling's_approximation
import np
n! ~ np.sqrt(2*np.pi*n)*(n/np.e)**n
for large n values. This calculation is literally instantaneous.
Maybe you can try to make use of threads.

How to convert floating point number to base 3 in python

How does one convert a base-10 floating point number in Python to a base-N floating point number?
Specifically in my case, I would like to convert numbers to base 3 (obtain the representation of floating point numbers in base 3), for calculations with the Cantor set.
After a bit of fiddling, here's what I came up with. I present it to you humbly, keeping in mind Ignacio's warning. Please let me know if you find any flaws. Among other things, I have no reason to believe that the precision argument provides anything more than a vague assurance that the first precision digits are pretty close to correct.
def base3int(x):
x = int(x)
exponents = range(int(math.log(x, 3)), -1, -1)
for e in exponents:
d = int(x // (3 ** e))
x -= d * (3 ** e)
yield d
def base3fraction(x, precision=1000):
x = x - int(x)
exponents = range(-1, (-precision - 1) * 2, -1)
for e in exponents:
d = int(x // (3 ** e))
x -= d * (3 ** e)
yield d
if x == 0: break
These are iterators returning ints. Let me know if you need string conversion; but I imagine you can handle that.
EDIT: Actually looking at this some more, it seems like a if x == 0: break line after the yield in base3fraction gives you pretty much arbitrary precision. I went ahead and added that. Still, I'm leaving in the precision argument; it makes sense to be able to limit that quantity.
Also, if you want to convert back to decimal fractions, this is what I used to test the above.
sum(d * (3 ** (-i - 1)) for i, d in enumerate(base3fraction(x)))
Update
For some reason I've felt inspired by this problem. Here's a much more generalized solution. This returns two generators that generate sequences of integers representing the integral and fractional part of a given number in an arbitrary base. Note that this only returns two generators to distinguish between the parts of the number; the algorithm for generating digits is the same in both cases.
def convert_base(x, base=3, precision=None):
length_of_int = int(math.log(x, base))
iexps = range(length_of_int, -1, -1)
if precision == None: fexps = itertools.count(-1, -1)
else: fexps = range(-1, -int(precision + 1), -1)
def cbgen(x, base, exponents):
for e in exponents:
d = int(x // (base ** e))
x -= d * (base ** e)
yield d
if x == 0 and e < 0: break
return cbgen(int(x), base, iexps), cbgen(x - int(x), base, fexps)
Although 8 years have passed, I think it is worthwhile to mention a more compact solution.
def baseConversion( x=1, base=3, decimals=2 ):
import math
n_digits = math.floor(-math.log(x, base))#-no. of digits in front of decimal point
x_newBase = 0#initialize
for i in range( n_digits, decimals+1 ):
x_newBase = x_newBase + int(x*base**i) % base * 10**(-i)
return x_newBase
For example calling the function to convert the number 5+1/9+1/27
def baseConversion( x=5+1/9+1/27, base=3, decimals=2 )
12.01
def baseConversion( x=5+1/9+1/27, base=3, decimals=3 )
12.011
You may try this solution to convert a float string to a given base.
def eval_strint(s, base=2):
assert type(s) is str
assert 2 <= base <= 36
###
### YOUR CODE HERE
###
return int(s,base)
def is_valid_strfrac(s, base=2):
return all([is_valid_strdigit(c, base) for c in s if c != '.']) \
and (len([c for c in s if c == '.']) <= 1)
def eval_strfrac(s, base=2):
assert is_valid_strfrac(s, base), "'{}' contains invalid digits for a base-{} number.".format(s, base)
stg = s.split(".")
float_point=0.0
if len(stg) > 1:
float_point = (eval_strint(stg[1],base) * (base**(-len(stg[1]))))
stg_float = eval_strint(stg[0],base) + float_point
return stg_float

Categories