In programming, I used only Integers. But this time for some calculations. I need to calculate Euler-Mascheroni Constant γ . up to n-th decimal.{Though n ∈ [30, 150] is enough for me.
[x] = gif(x) = math.floor(x)
But, I doubt the precision
Numerical Algorithm
I need higher degree of accuracy using Python.
From the French Wikipedia discussion page, an approximation to 6 decimal places:
import math as m
EulerMascheroniApp = round( (1.-m.gamma(1+1.e-8))*1.e14 )*1.e-6
print(EulerMascheroniApp)
# 0.577216
This constant is also available in the sympy module, under the name EulerGamma:
>>> import sympy
>>> sympy.EulerGamma
EulerGamma
>>> sympy.EulerGamma.evalf()
0.577215664901533
>>> - sympy.polygamma(0,1)
EulerGamma
>>> sympy.stieltjes(0)
EulerGamma
>>> sympy.stieltjes(0, 1)
EulerGamma
Documentation:
math.gamma;
sympy.EulerGamma;
sympy.functions.special;
sympy: numerical evaluation.
On this last documentation link, you can find more information about how to evaluate the constant with more precision, if the default of .evalf() is not enough.
If you still want to compute the constant yourself as an exercise, I suggest comparing your results to sympy's constant, to check for accuracy and correctness.
You can calculate it using python Decimal built-in module to control how many decimals (https://docs.python.org/2/library/decimal.html) you are going to use.
a = 1/7
len(str(a))-2
Out[1] 17
using Decimal:
from decimal import *
getcontext().prec = 90 #90 decimals precision
a = Decimal(1) / Decimal(7)
len(str(a))-2
Out[2] 90
basically:
n = 100000
Euler_Mascheroni = -Decimal(log(Decimal(n))) + sum([Decimal(1)/Decimal(i) for i in range(1,n)])
Euler_Mascheroni
Out[3] Decimal('0.577210664893199330073570099082905499710324918344701101627529415938181982282214')
finally, you can "arbitrarily" increase precision:
from decimal import *
from math import log
def Euler_Mascheroni(n,nth_decimals = 80):
getcontext().prec = nth_decimals
SUM = Decimal(0)
for i in range(1,n):
SUM+=Decimal(1)/Decimal(i)
return -Decimal(log(Decimal(n))) + SUM
Euler_Mascheroni(100000000,nth_decimals = 120)
which gives:
Decimal('0.5772156599015311156682000509495086978690376512201034388184221886576113026091829254475798266636558124658249350393045066')
Answering comment from #Stef
EM = Decimal(0.57721566490153286060651209008240243104215933593992)#reference taken from wikipedia
n = 100000000
Decimal(log(Decimal(n)))
getcontext().prec = 100
SUM = Decimal(0)
for i in range(1,n):
SUM+=Decimal(1)/Decimal(i)
EM - (SUM-Decimal(log(Decimal(n))))
will give
Decimal('5.00000174 ... 85E-9')
Related
When I calculated 24! using math library, the result is different compared to 24! calculated by dividing 25! by 25. Why is this?
>>> import math
>>> f=math.factorial(25)
>>> int(f/25)
620448401733239409999872
>>> math.factorial(24)
620448401733239439360000
>>>
/ performs "true division". The result is a floating point number, which does not have enough precision to represent the exact quotient. Calling int cannot reverse the precision loss. The errors in floating point math & rounding are causing the discrepancy.
// is integer division - which is what you want:
>>> f = math.factorial(25)
>>> f/25
6.204484017332394e+23
>>> int(f/25)
620448401733239409999872
>>> math.factorial(24)
620448401733239439360000
>>> f//25
620448401733239439360000 # correct answer
you must not use / operation and int() after division. this code will round the exact division. but when you use factorial for 24 python is using * operations.
>>> from math import factorial
>>> f25 = factorial(25)
>>> f25
# 620448401733239439360000
here you can use // instead of / operation.
see operations explanation here.
>>> f24 = factorial(24)
620448401733239439360000
>>> f25 // 25
620448401733239439360000
I saw here how to find the sqrt(2) up to 100 digits in python:
import decimal
number = decimal.Decimal(2)
precision = decimal.Context(prec = 100)
print (number.sqrt(precision))
I tested and worked fine. When I try to use this code to pi, the print doesn't work. I tried
print (number.(precision)), print (number(precision)), etc. How the last line should be?
import decimal
number = decimal.Decimal(math.pi)
precision = decimal.Context(prec = 100)
print (???)
I'm using netbeans. I can, however, print the sqrt(pi).
EDIT: Thanks, guys!
Python returns:
3.141592653589793-1-159979634685441851615905761718750
Wolfram returns
3.141592653589793-2-384626433832795028841971693993751
Only after 14 digits the answer's diverges. Is math.pi from python reliable?
Strange enough, but the sqrt(2) up to 1000 digits in python and wolfram gives the same answer.
You can do what you want using format and specifying the number of places:
from math import pi
print (format (pi,'.100f'))
Another solution is by using the mpmath library:
from mpmath import mp
mp.dps = 100 # set number of digits
print(mp.pi)
Another possibility:
import math
from decimal import getcontext, Decimal
getcontext().prec = 100
number = Decimal(math.pi)
print(number)
Other answer are correct for printing with certain precision. However, if you try them with Decimal(math.pi) you will get 3.141592653589793115997963468544185161590576171875, obviously less than 100 digits, and even these digits are not all correct. Reason for this is that math.pi is float, which has limited precision.
To actually calcute correct digits of pi to any precision you can use this code (taken from official Python documentation for decimal library):
def pi():
"""Compute Pi to the current precision.
>>> print(pi())
3.141592653589793238462643383
"""
getcontext().prec += 2 # extra digits for intermediate steps
three = Decimal(3) # substitute "three=3.0" for regular floats
lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
while s != lasts:
lasts = s
n, na = n+na, na+8
d, da = d+da, da+32
t = (t * n) / d
s += t
getcontext().prec -= 2
return +s # unary plus applies the new precision
This presumes you have set getcontext().prec to wanted precision.
If you just want to print the number with a certain precision do the following:
from decimal import Decimal
number = decimal.Decimal(math.pi)
print(format(number,'.100f'))
Otherwise, you may do the following to set the precision:
from decimal import getcontext, Decimal
getcontext().prec = 100
number = Decimal(math.pi)
print(number)
I am attempting to write a Python program which will produce an approximation for e using a Taylor series to a user-defined length (e.g. 100 decimal places) and print all 100 digits. However, the output is never longer than 15 decimal places, which is python's default precision for numpy.e. How could I resolve this? Below is the code I was using.
import math
precision = int(input("Number of decimal places = "))
e = 0
s = 1
i = 1
while s > (10**(-1*precision)):
e = e + s
s = 1/math.factorial(i) # e = 1 + 1/1! + 1/2! + 1/3! + ...
i = i + 1
print(e)
I think you can use sympy and mpmath.
First to figure out the number of terms we need from the error in Taylor series at x=0 and evaluated at 1,
1/n! e^1 < 1e-100
and taking n=75 is enough. Though we can just use 100 and this should also be good enough.
In sympy we create the Taylor series of e^x at 0 and then evaluate it at 1,
import sympy, mpmath
f = 0
for i in range(0, 100):
f += 1/sympy.factorial(i)
mpmath.mp.dps = 100
print(mpmath.mpf(f))
which gives me the value of
2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427
So imagine I have
>>> a = 725692137865927813642341235.00
If I do
>>> sum = a + 1
and afterwards
>>> sum == a
True
This is because a is bigger than a certain threshold.
Is there any trick like the logsumexp to perform this?
PS: a is an np.float64.
If a has to be specifically of type float, no, then that's not possible. In fact, the imprecision is much greater:
>>> a = 725692137865927813642341235.00
>>> a + 10000 == a
True
However, there are other data types that can be used to represent (almost) arbitrary precision decimal values or fractions.
>>> d = decimal.Decimal(a)
>>> d + 1 == d
False
>>> f = fractions.Fraction(a)
>>> f + 1 == f
False
(Note: of course, doing Decimal(a) or Fraction(a) does not magically restore the already lost precision of a; if you want to preserve that, you should pass the full value as a string.)
0) import decimal
1) setup appropriate precision of the decimal.getcontext() ( .prec attribute )
2) declare as decimal.Decimal() instance
>>> import decimal
>>> decimal.getcontext().prec
28
>>> decimal.getcontext().prec = 300
>>> dec_a = decimal.Decimal( '725692137865927813642341235.0' )
It is a pleasure to use decimal module for extremely extended numerical precision solvers.
BONUS:
Decimal module has very powerful context-methods, that preserve the decimal-module's strengths .add(), .subtract(), .multiply(), .fma(), .power() so as to indeed build an almost-infinite precision solver methods ...
Definitely worth mastering these decimal.getcontext() methods - your solvers spring into another league in precision and un-degraded convergence levels.
Will dividing a by 100,000 then adding 1 then times it back up again?
Eg.
a=725692137865927813642341235.00
a /= 100000
a += 0.00001
a *= 100000
I'm trying to continue on my previous question in which I'm trying to calculate Fibonacci numbers using Benet's algorithm. To work with arbitrary precision I found mpmath. However the implementation seems to fail above certain value. For instance the 99th value gives:
218922995834555891712
This should be (ref):
218922995834555169026
Here is my code:
from mpmath import *
def Phi():
return (1 + sqrt(5)) / 2
def phi():
return (1 - sqrt(5)) / 2
def F(n):
return (power(Phi(), n) - power(phi(), n)) / sqrt(5)
start = 99
end = 100
for x in range(start, end):
print(x, int(F(x)))
mpmath does do arbitrary precision math, and it does do it accurately to any precision (as described above) if you are using the arbitrary precision math module and not the default behavior.
mpmath has more than one module which determines the accuracy and speed of the results (to be chosen depending on what you need), and by default it uses Python floats, which is what I believe you saw above.
If you call mpmath's fib( ) having set mp.dps high enough, you will get the correct answer as stated above.
>>> from mpmath import mp
>>> mp.dps = 25
>>> mp.nprint( mp.fib( 99 ), 25 )
218922995834555169026.0
>>> mp.nprint( mpmath.fib( 99 ), 25 )
218922995834555169026.0
Whereas, if you don't use the mp module, you will only get results as accurate as a Python double.
>>> import mpmath
>>> mpmath.dps = 25
>>> mpmath.nprint( mpmath.fib( 99 ), 25
218922995834555170816.0
mpmath provides arbitrary precision (as set in mpmath.mp.dps), but still inaccuate calculation. For example, mpmath.sqrt(5) is not accurate, so any calculation based on that will also be inaccurate.
To get an accurate result for sqrt(5), you have to use a library which supports abstract calculation, e.g. http://sympy.org/ .
To get an accurate result for Fibonacci numbers, probably the simplest way is using an algorithm which does only integer arithmetics. For example:
def fib(n):
if n < 0:
raise ValueError
def fib_rec(n):
if n == 0:
return 0, 1
else:
a, b = fib_rec(n >> 1)
c = a * ((b << 1) - a)
d = b * b + a * a
if n & 1:
return d, c + d
else:
return c, d
return fib_rec(n)[0]
Actually mpmath's default precision is 15 which I think is not enough if you want to get the result of up to 21-digit precision.
One thing you can do is set the precision to be a higher value and use mpmath's defined arithmetic functions for addition, subtraction, etc.
from mpmath import mp
mp.dps = 50
sqrt5 = mp.sqrt(5)
def Phi():
return 0.5*mp.fadd(1, sqrt5)
def phi():
return 0.5*mp.fsub(1, sqrt5)
def F(n):
return mp.fdiv(mp.power(Phi(), n) - mp.power(phi(), n), sqrt5)
print int(F(99))
This will give you
218922995834555169026L