Setting longer default decimal precision

K

Kay Y. Jheallee

Using 1/3 as an example,
33.33333333333333570180911920033395290374755859375000

which seems to mean real (at least default) decimal precision
is limited to "double", 16 digit precision (with rounding error).
Is there a way to increase the real precision, preferably as
the default?
For instance, UBasic uses a "Words for fractionals", f,
"Point(f)" system, where Point(f) sets the decimal display
precision, .1^int(ln(65536^73)/ln(10)), with the last few digits
usually garbage.
Using "90*(pi/180)*180/pi" as an example to highlight the
rounding error (4 = UBasic's f default value):

Point(2)=.1^09: 89.999999306
Point(3)=.1^14: 89.9999999999944
Point(4)=.1^19: 89.9999999999999998772
Point(5)=.1^24: 89.999999999999999999999217
Point(7)=.1^33: 89.999999999999999999999999999999823
Point(10)=.1^48: 89.999999999999999999999999999999999999999999997686
Point(11)=.1^52:
89.9999999999999999999999999999999999999999999999999632

If not in the core program, is there a higher decimal precision
module that can be added?
 
S

Steven D'Aprano

Using 1/3 as an example,

[snip examples]
which seems to mean real (at least default) decimal precision is limited
to "double", 16 digit precision (with rounding error).

That's because Python floats actually are implemented as C doubles. And
no, they're not configurable.

However, Python also has a Decimal class, which (unlike floats) are
actually decimal rather than binary, and include configurable precision.
There is a performance hit -- prior to Python version 3.3, Decimal was
quite slow, but in 3.3 they got a major speed increase and are now nearly
as fast as floats.

An example:

py> import decimal
py> x = decimal.Decimal(1)/3
py> decimal.getcontext().prec = 50
py> y = decimal.Decimal(1)/3
py> print(x, y)
0.3333333333333333333333333333
0.33333333333333333333333333333333333333333333333333
 
D

Dennis Lee Bieber

Using 1/3 as an example,

33.33333333333333570180911920033395290374755859375000

which seems to mean real (at least default) decimal precision

The default double precision FLOATING POINT is limited to ~15
significant digits. That's a hardware limit for double on most machines
(64-bits). Most floating point processors may use 80 bits internally, but
truncate back down on output.

Python has supported a DECIMAL package for some years, but math with
that package will be slower as it can't go through the FPU.

Check the help file for your installation, look for decimal
 
S

Steven D'Aprano

Hi Kay,

You emailed me off-list, but your email address is bouncing or invalid,
so I have no way to email you back.

Unless you have something private or personal to say, you should keep
replies on the list here so that others can either answer your questions
or learn from the responses. If you do have something private to say, you
should use a real email address that accepts replies :)

I'm taking the liberty of republishing your comments to me here:

[you wrote]
Okay,but after I import "math" and "decimal",

py> decimal.getcontext().prec=75
py> print decimal.Decimal(math.atan(1))
0.78539816339744827899949086713604629039764404296875

though I set precision to 75, it only did the trig function to 50
places AND it is only right to 16 places,

0.785398163397448309615660845819875721049292349843776...(actual).
[end quote]


Here, you calculate the atan of 1 using floating point maths, that is, to
the precision of C doubles (about 17 decimal places). After the
calculation is performed using float, you then convert it to a Decimal,
but it is too late, you can't retroactively regain precision.

In a perfect world, this would work:

math.atan(Decimal(1))

but alas, all the functions in the math module convert their arguments to
float first, so even though your Decimal(1) could perform calculations to
75 decimal places, the math.atan function downgrades it to a regular
float.

Unfortunately, Decimals don't support high-precision trig functions. If
you study the decimal.py module, you could possibly work out how to add
support for trig functions, but they have no current support for them.

You could try this third-party module:

http://code.google.com/p/mpmath/‎

which claims to be arbitrary-precision maths for Python, but I've never
used it.
 
O

Oscar Benjamin

but alas, all the functions in the math module convert their arguments to
float first, so even though your Decimal(1) could perform calculations to
75 decimal places, the math.atan function downgrades it to a regular
float.

Unfortunately, Decimals don't support high-precision trig functions. If
you study the decimal.py module, you could possibly work out how to add
support for trig functions, but they have no current support for them.

The documentation has examples for how to make high precision sin()
and cos() functions that work with Decimals.
http://docs.python.org/2/library/decimal.html#recipes

The basic idea is to sum terms of the Maclaurin series until it
converges. For atan(x) the Maclaurin series is

atan(x) = x - (1/3)x**3 + (1/5)x**5 - (1/7)x**7 + (1/9)x**9 + ...

The nth term is given by f(n) = ((-1)**n)*(1/(2n+1))*x**(2n+1).

The ratio test gives that that |f(n+1)/f(n)| = (2(n+1)+1)/(2n + 1) *
x**2 which has a limiting value of x**2 so the series converges for
|x| < 1 (unlike sin() and cos() that converge for all x). For values
outside this range you can use the identity arctan(1/x) ==
sign(x)*pi/2 - arctan(x) to map the values back into the convergent
range. This may still be problematic when x is close to 1 in which
case an alternate Taylor series around x=1 could be used. You'd need
to ensure that you were using enough digits for pi as well if you
wanted to make this work.

It's probably easiest just to use the mpmath library as Steven
suggested (or gmpy2, or sympy which includes mpmath).


Oscar
 
K

Kay Y. Jheallee

On 13.Nov.20.Wed 14:02, Steven D'Aprano wrote:> Hi Kay,
You emailed me off-list, but your email address is bouncing or invalid,
so I have no way to email you back.

So THAT's where it went! Sorry about that...yes, it WAS meant
for the group :/!
[you wrote]
Okay,but after I import "math" and "decimal",

py> decimal.getcontext().prec=75
py> print decimal.Decimal(math.atan(1))
0.78539816339744827899949086713604629039764404296875

though I set precision to 75, it only did the trig function to
50 places AND it is only right to 16 places,

0.785398163397448309615660845819875721049292349843776...
(actual).
[end quote]


Here, you calculate the atan of 1 using floating point maths,
that is, to the precision of C doubles (about 17 decimal
places). After the calculation is performed using float, you
then convert it to a Decimal,
but it is too late, you can't retroactively regain precision.

In a perfect world, this would work:

math.atan(Decimal(1))

but alas, all the functions in the math module convert their
arguments to float first, so even though your Decimal(1)
could perform calculations to 75 decimal places, the
math.atan function downgrades it to a regular float.

Then that is useless! :(
You could try this third-party module:

http://code.google.com/p/mpmath/‎

Ah, that looks like just the puppy I'm looking for. :)
Okay then, I just installed the PortableApps version of Python,
but when I downloaded "mpmath-0.17.win32" the installer aborted
with "No Python installation found in the registry".
So I'm trying to install "setuptools 1.4" (and do it that way) at

https://pypi.python.org/pypi/setuptools/1.4

but where is the "Download" link ("Downloads" just shifts down to
the page section)? I'm just looking for the ".zip" file version
(if one exists), not ".tar.gz".
Thx!
 
T

Tim Golden

Advice from a long time Python Windows user that's aimed at everybody,
not just the OP. Always try and find a binary installer, it's far
easier than messing about with ".zip" or ".tar.gz" files. In particular
it avoids the infamous "error: Unable to find vcvarsall.bat", which in
plain English means you've not got Visual C++ installed or you've got
the wrong version.

A very good site to find binaries is this
http://www.lfd.uci.edu/~gohlke/pythonlibs/. You can safely ignore the
"Unofficial" at the top of the page, I've been using stuff from there
for years and never, ever had a problem.

While Mark's advice here is fairly sound, the OP pointed out that they
are using PortableApps Python (which I've never tried myself). The key
point is that the binary installers expect to find a Python entry in the
registry to show them where to go.

For now I'm lazily going to point to the effbot's 10-year-old page on
the subject:

http://effbot.org/zone/python-register.htm

with the proviso that, if that doesn't work, the OP should come back and
we'll try to help some more.

If it's any consolation, this business (bootstrapping installation on
Windows) is improving, piece by piece. It's just not all there yet.

TJG
 
T

Tim Golden

Ah, that looks like just the puppy I'm looking for. :)
Okay then, I just installed the PortableApps version of Python,
but when I downloaded "mpmath-0.17.win32" the installer aborted with "No
Python installation found in the registry".
So I'm trying to install "setuptools 1.4" (and do it that way) at

https://pypi.python.org/pypi/setuptools/1.4

but where is the "Download" link ("Downloads" just shifts down to the
page section)? I'm just looking for the ".zip" file version (if one
exists), not ".tar.gz".

Yes, unfortunately you seem to have hit the "sour spot" of installation:
Windows with a Portable Python.

I note that the setuptools page has a .whl, which is the brand new
Python binary installer. Although designed to be installed with tool
support, it is in fact a .zip file which you should be able to unpack
into c:\python<xy>\lib\site-packages. It might be worth a try.

Please feel to come back for more help if needs be: you've hit an
unfortunately bumpy patch in the Python experience and I'd prefer to
smooth things out for you than have to turn away in disgust :)

TJG
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top