0

Is there a better (faster, more efficient, or "just more pythonic") way than my way in rounding Decimals in Python? I came up with the following:

sign, digits, exponent = the_number.as_tuple()
Decimal((sign, digits[:exponent+len(digits)+decimal_places],-decimal_places))

edit: I ended up using yet another solution that is faster[1] and also "fills" the decimal to the wanted precision:

decimal.Decimal('%.*f' % (decimal_places, number))

[1] It is faster up to ~200 decimal places. In my case I get a random float-value I want to "cast" to decimal, so the original precision is already limited and << 200.

causa prima
  • 1,502
  • 1
  • 14
  • 24
  • You are not just rounding; your code changes the value of the decimal. Is that what you want? For example, `the_number = Decimal('1000')` becomes `Decimal('0.01000')` if `decimal_places = 5`. – unutbu Oct 06 '14 at 18:10
  • No, that is not intended, but simply wrong. I did not think about integer decimals as they won't ever happen in my code. But still my code is wrong and I won't use it just to be safe ;) – causa prima Oct 07 '14 at 13:20
  • Do you want to round to a particular exponent (e.g., to the nearest tenth, or to some number of places after the decimal point), or do you want to round to a particular number of significant digits? – Mark Dickinson Oct 07 '14 at 17:59
  • https://stackoverflow.com/a/63035788/3907629 – NMC Jul 22 '20 at 14:01

2 Answers2

1

What about round (builtin):

>>> the_number = decimal.Decimal(1.23456789)
>>> round(the_number, 2)
Decimal('1.23')
>>> d=decimal.Decimal("31.100")
>>> d
Decimal('31.100')
>>> round(d, 10)
Decimal('31.1000000000')
>>> round(d, 20)
Decimal('31.10000000000000000000')
>>> round(d, 24)
Decimal('31.100000000000000000000000')
>>> round(d, 26)
Decimal('31.10000000000000000000000000')
>>> round(d, 1)
Decimal('31.1')
>>> round(d, 0)
Decimal('31')
matsjoyce
  • 5,744
  • 6
  • 31
  • 38
  • using round(n,decimal_places) with n = Decimal(31.100) always returns Decimal("31.1") no matter the value of decimal_places, although n is Decimal('31.10000000000000142108547152020037174224853515625') – causa prima Oct 07 '14 at 13:16
  • 1
    Use float instead of string for construction, i.e. Decimal(31.100) instead of Decimal('31.100'), and it "won't work". If you print the decimal, all the decimal places from the float used on cunstruction are show. When rounding, the "intended" decimal is magically restored - how does that work? I will have to look into the source. Meanwhile, your answer seems to be correct, I just don't understand the magic of round() ;) – causa prima Oct 08 '14 at 13:11
  • I accepted your answer now because it is much faster than the one from user3666197, and still does what it should. – causa prima Oct 08 '14 at 14:09
1

May try:

with decimal.localcontext() as ctx:
    ctx.prec = aWantedPRECISION          # temporarily adapt precision to aWantedPRECISION
    result   = +the_number               # set

if this is Pythonic-enough

user3666197
  • 1
  • 6
  • 50
  • 92
  • Great! I though about changing the precision locally, but did not come up with a nice solution like yours. Thanks! – causa prima Oct 07 '14 at 13:24