Significant figures in the decimal module

So I've decided to try to solve my physics homework by writing some python scripts to solve problems for me. One problem that I'm running into is that significant figures don't always seem to come out properly. For example this handles significant figures properly:

from decimal import Decimal
>>> Decimal('1.0') + Decimal('2.0')
Decimal("3.0")

But this doesn't:

>>> Decimal('1.00') / Decimal('3.00')
Decimal("0.3333333333333333333333333333")

So two questions:

  1. Am I right that this isn't the expected amount of significant digits, or do I need to brush up on significant digit math?
  2. Is there any way to do this without having to set the decimal precision manually? Granted, I'm sure I can use numpy to do this, but I just want to know if there's a way to do this with the decimal module out of curiosity.


Asked by: Edgar469 | Posted: 06-10-2021






Answer 1

Changing the decimal working precision to 2 digits is not a good idea, unless you absolutely only are going to perform a single operation.

You should always perform calculations at higher precision than the level of significance, and only round the final result. If you perform a long sequence of calculations and round to the number of significant digits at each step, errors will accumulate. The decimal module doesn't know whether any particular operation is one in a long sequence, or the final result, so it assumes that it shouldn't round more than necessary. Ideally it would use infinite precision, but that is too expensive so the Python developers settled for 28 digits.

Once you've arrived at the final result, what you probably want is quantize:

>>> (Decimal('1.00') / Decimal('3.00')).quantize(Decimal("0.001"))
Decimal("0.333")

You have to keep track of significance manually. If you want automatic significance tracking, you should use interval arithmetic. There are some libraries available for Python, including pyinterval and mpmath (which supports arbitrary precision). It is also straightforward to implement interval arithmetic with the decimal library, since it supports directed rounding.

You may also want to read the Decimal Arithmetic FAQ: Is the decimal arithmetic ‘significance’ arithmetic?

Answered by: Rafael539 | Posted: 07-11-2021



Answer 2

Decimals won't throw away decimal places like that. If you really want to limit precision to 2 d.p. then try

decimal.getcontext().prec=2

EDIT: You can alternatively call quantize() every time you multiply or divide (addition and subtraction will preserve the 2 dps).

Answered by: David588 | Posted: 07-11-2021



Answer 3

Just out of curiosity...is it necessary to use the decimal module? Why not floating point with a significant-figures rounding of numbers when you are ready to see them? Or are you trying to keep track of the significant figures of the computation (like when you have to do an error analysis of a result, calculating the computed error as a function of the uncertainties that went into the calculation)? If you want a rounding function that rounds from the left of the number instead of the right, try:

def lround(x,leadingDigits=0): 
    """Return x either as 'print' would show it (the default) 
    or rounded to the specified digit as counted from the leftmost 
    non-zero digit of the number, e.g. lround(0.00326,2) --> 0.0033
    """ 
    assert leadingDigits>=0 
    if leadingDigits==0: 
            return float(str(x)) #just give it back like 'print' would give it
    return float('%.*e' % (int(leadingDigits),x)) #give it back as rounded by the %e format  

The numbers will look right when you print them or convert them to strings, but if you are working at the prompt and don't explicitly print them they may look a bit strange:

>>> lround(1./3.,2),str(lround(1./3.,2)),str(lround(1./3.,4))
(0.33000000000000002, '0.33', '0.3333')

Answered by: Lenny263 | Posted: 07-11-2021



Answer 4

Decimal defaults to 28 places of precision.
The only way to limit the number of digits it returns is by altering the precision.

Answered by: Lenny372 | Posted: 07-11-2021



Answer 5

What's wrong with floating point?

>>> "%8.2e"%  ( 1.0/3.0 )
'3.33e-01'

It was designed for scientific-style calculations with a limited number of significant digits.

Answered by: Fenton978 | Posted: 07-11-2021



Answer 6

If I undertand Decimal correctly, the "precision" is the number of digits after the decimal point in decimal notation.

You seem to want something else: the number of significant digits. That is one more than the number of digits after the decimal point in scientific notation.

I would be interested in learning about a Python module that does significant-digits-aware floating point point computations.

Answered by: Dexter801 | Posted: 07-11-2021



Similar questions

python - Only match figures with n number of decimal places

.500 265.0000 1.000 4.0319 How can I just match just .500 and 1.000 or just 265.0000 and 4.0319 on the basis of them having 3 vs 4 digits to the right of the decimal point? Assume I don't know ahead of time how many digits there will be to the left of the decimal.


python - Format float to 3 significant figures after decimal point

How would you format a float to three signicant figures after a decimal place? If the float has no decimal places then the number should remain the same. This is correct: '{0:.3}'.format(0.000325658) '0.000326' This is incorrect: '{0:.3}'.format(325256.023) '3.25e+05' and should be 325256.023 The value 325256.0


python - Only match figures with n number of decimal places

.500 265.0000 1.000 4.0319 How can I just match just .500 and 1.000 or just 265.0000 and 4.0319 on the basis of them having 3 vs 4 digits to the right of the decimal point? Assume I don't know ahead of time how many digits there will be to the left of the decimal.


python - Format float to 3 significant figures after decimal point

How would you format a float to three signicant figures after a decimal place? If the float has no decimal places then the number should remain the same. This is correct: '{0:.3}'.format(0.000325658) '0.000326' This is incorrect: '{0:.3}'.format(325256.023) '3.25e+05' and should be 325256.023 The value 325256.0


math - How to round a number to significant figures in Python

I need to round a float to be displayed in a UI. e.g, to one significant figure: 1234 -> 1000 0.12 -> 0.1 0.012 -> 0.01 0.062 -> 0.06 6253 -> 6000 1999 -> 2000 Is there a nice way to do this using the Python library, or do I have to write it myself?


python - plot from a large data set into several figures

I have a large set of particle position data from a movie made by a detection camera in a physical experiment. The first column just gives the frame number, the second to fourth column is x, y, and z position. Now I would like to plot the x and y position for the first 10 frames, but for each frame in a different figure. I'm using the compress command to extract the data of each frame. Here's my code so far:


python - Only match figures with n number of decimal places

.500 265.0000 1.000 4.0319 How can I just match just .500 and 1.000 or just 265.0000 and 4.0319 on the basis of them having 3 vs 4 digits to the right of the decimal point? Assume I don't know ahead of time how many digits there will be to the left of the decimal.


python - Saving figures in a loop

I don't know if this is possible and I hope to acurally portray what I wish to accomplish. Say we have: from pylab import * import matplotlib.pyplot as plt %matplotlib inline fig = plt.figure(figsize=(10,10)) y = 2 for x in xrange(0,5): value = [1,int(y)] plt.plot(value) plt.savefig("value" + y + ".png") y+=1 So my goal here is to get 5 plots (or I think this wo...


python - Why doesn't this code save my figures with titles?

I'm producing some figures with the following code: def boxplot_data(self,parameters_file,figure_title): data = pandas.read_csv(parameters_file) header = data.keys() number_of_full_subplots = len(header)/16 remainder = len(header)-(16*number_of_full_subplots) try: for i in range(number_of_full_subplots+1): fig =plt.figure(i) txt = fig.suptitle(figure_title...


python - How to send list of figures into Bokeh vplot()

I'm building up a list of plots programatically in a Python list and I'd like to throw it at the vplot function instead of the grid I'm currently using. The documentation has the explicit enumeration of the children but I'm wondering if I can take a list of figure objects and receive them into vplot somehow much like how is done for the grid object. channelPlots = [] for channel i...


python - Spyder won't plot figures inline

I have somehow messed up my Spyder configuration and the plots are no longer shown inline (in the IPython console). I followed the steps, described here: Spyder Plot Inline But I don't want to reset my configuration in order to get it work. Is there another way? I tried around a lot but can't figure it out.


python memory issues using 'for loop' and figures

My overall issue is clearing memory. The issue is now split into two sections. First is unreleased memory used by a 'for' loop. I used memory_profiler to line by line see the memory usage. the lines in question are: For the overall loop Line # Mem usage Increment Line Contents ================================================ 1266 275.6 MiB 171.9 MiB ...


numpy - Create a grid from figures python

Im new to python, Im trying to create a 3X4 grid figure of 12 figures, the figures looks like that :  


python - How to create array with figures and to be able to move each figure, not only last added in array?

I want to create a few figures which only have difference in coordinates, but same in other properties. But my code allows me to control and move only last added to array figure, so what shoud I do to be able to move every figure, can you explain? class car(pygame.sprite.Sprite): def __init__(self,x,y): pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load(os.path.join(IMG, "car.png"))....






Still can't find your answer? Check out these communities...



PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python



top