Python Forum
Precision with Decimal Type - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Precision with Decimal Type (/thread-41442.html)



Precision with Decimal Type - charlesrkiss - Jan-16-2024

I'm having some problems with getting the desired precision, and something like this also happens.

>>> G=Decimal(0.999999999999999999999900000000000000)
>>> print(G)
1

What am I doing wrong?

See the text and image below for extra stuff, when I was working with theta. Theta was generated in the same python script and session:

import math
import decimal
from decimal import getcontext


getcontext().prec = 36

theta = decimal.Decimal(1/2 * math.asin(2 * (F/N)))

theta: 1.00000000000000010105568267120302867849435113356548754381947219371795654296875E-11

C = decimal.Decimal(math.cos(theta))

C: 1


Thank you for reading this!

[attachment=2708]


RE: Precision with Decimal Type - rob101 - Jan-16-2024

Should that not be G=Decimal("0.999999999999999999999900000000000000")?

Have a look at the Numeric and Mathematical Modules — Python 3.12.1 documentation


RE: Precision with Decimal Type - charlesrkiss - Jan-16-2024

Thank you so much for your reply! It's been very helpful.

Your solution definitely works for something like this, as you recommended:

>>> G=Decimal('0.999999999999999999999900000000000000')
>>> print(G)
0.999999999999999999999900000000000000
But it's not working for me when I pass a variable to cos or sin (with or without quotation marks). The cos function rounds to one, and the sin output just repeats the value of theta in this case (instead of rounding to zero, for example). Weird:

>>> theta=Decimal('1.00000000000000010105568267120302867849435113356548754381947219371795654296875E-11')
>>> print(math.cos(theta))
1.0
>>> B=Decimal(math.cos(theta))
>>> print(B)
1
>>> B=Decimal(math.sin(theta))
>>> print(B)
1.00000000000000010105568267120302867849435113356548754381947219371795654296875E-11


Not even the example of def cos(x) from the man page is working atm as I expected, argh : https://docs.python.org/3/library/decimal.html?highlight=cosine#Recipes:~:text=%2Bs%0A%0Adef-,cos,-(x)%3A

>>> print(cos(0.5))
0.8775825618903728
>>> print(cos(Decimal('0.5')))
0.8775825618903728
>>> getcontext().prec = 25
>>> print(cos(Decimal('0.5')))
0.8775825618903728
I'm using bash on Ubuntu. And it works the same on the PyCharm IDE.


RE: Precision with Decimal Type - charlesrkiss - Jan-17-2024

If your'e interested, here is the tiny script that I am having problems with. I have declared the decimal everywhere possible (even if not necessary). Some times decimal was declared in too many places and I had to remove them, accordingly, etc. I realize I have to study the decimal rules more.

This script has been through many versions. The most recent version is just the bare bones, testing (at this point). Below it, I posted the output.

Thank you!

import math
import decimal as dc
from decimal import *

getcontext().prec = 36

L = dc.Decimal(1000)  # (input('Enter the length of the pendulum: '))  # length of pendulum
F = dc.Decimal(1e-10)  # (input('What is the force of the mass acting on m1: '))  # force of mass
G = dc.Decimal(6.67e-11)  # gravitational constant
m1 = dc.Decimal(1.02)  # mass of pendulum
m2 = dc.Decimal(10.0)  # use m2 as an alternative, if desired
g = dc.Decimal(9.81)  # acceleration due to gravity
N = dc.Decimal(10.0)  # standard Newton of force
H = dc.Decimal(0.5)

R = dc.Decimal(math.sqrt((G * m1 * m2)/F))

theta = dc.Decimal(1/2 * math.asin(2 * (F/N)))
# theta = 1.00000000000000010105568267120302867849435113356548754381947219371795654296875E-11
C = dc.Decimal(math.cos(theta))
#S = (1 + C) * H


D = dc.Decimal(L * dc.Decimal(math.sin(theta)))
# d2 = decimal.Decimal(math.sqrt(decimal.Decimal((3+(math.cos(theta))) * (1+math.cos(theta)))))
# d = dc.Decimal(math.sin(math.acos(.5*(1+C))))
# v2 = dc.Decimal(math.sqrt(2 * g * d))

# T = dc.Decimal(math.sqrt(2 * g * d))/dc.Decimal(g)

print("theta: ", Decimal(theta))
print("R: ", R)
print("D: ", D)
# print("d: ", d)
# #print("v2: ", float(v2))
# print("T: ", T)
# print("S: ", S)
print("C: ", Decimal(C))

print("decimal: ", dc.getcontext())
OUTPUT:
 theta:  1.00000000000000010105568267120302867849435113356548754381947219371795654296875E-11
R:  2.608332800851915767026412140694446861743927001953125
D:  1.00000000000000010105568267120302868E-8
C:  1
decimal:  Context(prec=36, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[Inexact, FloatOperation, Rounded], traps=[InvalidOperation, DivisionByZero, Overflow])

Process finished with exit code 0
Thanks again!


RE: Precision with Decimal Type - perfringo - Jan-17-2024

Some things to consider:

Documentation > 6.Modules > 6.1. More on modules
Quote:Note that in general the practice of importing * from a module or package is frowned upon, since it often causes poorly readable code. However, it is okay to use it to save typing in interactive sessions.

decimal — Decimal fixed point and floating point arithmetic

Quote:The significance of a new Decimal is determined solely by the number of digits input. Context precision and rounding only come into play during arithmetic operations.



RE: Precision with Decimal Type - charlesrkiss - Jan-17-2024

Hello Perfringo,

You can see in the second balloon above (repeated below) how theta is close to a ninety-digit number that I input to math.cos, but my interpreter sends back a single digit, despite my two attempts (to force a decimal). What am I missing here?

>>> theta=Decimal('1.00000000000000010105568267120302867849435113356548754381947219371795654296875E-11')
>>> print(math.cos(theta))
1.0
>>> B=Decimal(math.cos(theta))
>>> print(B)
1
Thank you!



RE: Precision with Decimal Type - charlesrkiss - Jan-18-2024

There are some environment variables I need to look into, I imagine.


RE: Precision with Decimal Type - casevh - Jan-18-2024

(Jan-17-2024, 10:45 PM)charlesrkiss Wrote: Hello Perfringo,

You can see in the second balloon above (repeated below) how theta is close to a ninety-digit number that I input to math.cos, but my interpreter sends back a single digit, despite my two attempts (to force a decimal). What am I missing here?

>>> theta=Decimal('1.00000000000000010105568267120302867849435113356548754381947219371795654296875E-11')
>>> print(math.cos(theta))
1.0
>>> B=Decimal(math.cos(theta))
>>> print(B)
1
Thank you!

math.cos and math.sin only operate on float arguments. They convert Decimal values to float before making their calculations.

The gmpy2 library supports extended precision functions. Here is an example. Note that precision is given in bits instead of decimal digits.

>>> import gmpy2
>>> from gmpy2 import mpfr, get_context
>>> get_context().precision=300
>>> theta=mpfr('1.00000000000000010105568267120302867849435113356548754381947219371795654296875E-11')
>>> gmpy2.cos(theta)
mpfr('0.99999999999999999999994999999999999998989443214954636328820484997230230947904666795480390189',300)
>>> gmpy2.sin(theta)
mpfr('1.0000000000000001010556660045363620118226316828485940585416016349273349610972753087341444294e-11',300)
>>> theta
mpfr('1.00000000000000010105568267120302867849435113356548754381947219371795654296875e-11',300)
>>>
Disclosure: I maintain gmpy2. mpmath and bigfloat are similar libraries.


RE: Precision with Decimal Type - charlesrkiss - Jan-18-2024

Wow, amazing. Thank you, casevh !!


RE: Precision with Decimal Type - charlesrkiss - Jan-18-2024

I can't wait to work with these new libraries. Thank you!