Python Forum

Full Version: Precision with Decimal Type
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
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]
Should that not be G=Decimal("0.999999999999999999999900000000000000")?

Have a look at the Numeric and Mathematical Modules — Python 3.12.1 documentation
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/decima...os,-(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.
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!
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.
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!
There are some environment variables I need to look into, I imagine.
(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.
Wow, amazing. Thank you, casevh !!
I can't wait to work with these new libraries. Thank you!