On Fri, 9 Oct 2020 at 23:41, Tim Peters <tim.peters@gmail.com> wrote:

But the decimal spec takes a different approach, which Python's docs don't explain at all: the otherwise-mysterious ROUND_05UP rounding mode. Quoting from the spec:

http://speleotrove.com/decimal/damodel.html ... The rounding mode round-05up permits arithmetic at shorter lengths to be emulated in a fixed-precision environment without double rounding. For example, a multiplication at a precision of 9 can be effected by carrying out the multiplication at (say) 16 digits using round-05up and then rounding to the required length using the desired rounding algorithm.

In your original example, 1.01 * 1.46 rounds to 4-digit 1.474 under ROUND_05UP. and then `quantize()` can be used to round that back to 1, 2, or 3 digits under any rounding mode you like.

Or, with your last example,

with decimal.localcontext() as ctx: ... ctx.rounding = decimal.ROUND_05UP ... r = D('1.00000000000001')*D('1.49999999999996') r Decimal('1.499999999999974999999999999') r.quantize(D('.00000000000001')) Decimal('1.49999999999997')

And can't be this the default of decimal? For what I know, this is the default of BigDecimal in Java:

public BigDecimal multiply(BigDecimal multiplicand)

Returns a BigDecimal whose value is (this × multiplicand), and whose scale is (this.scale() + multiplicand.scale()). Parameters:multiplicand - value to be multiplied by this BigDecimal.Returns:this * multiplicand

public BigDecimal multiply(BigDecimal multiplicand, MathContext mc)

Returns a BigDecimal whose value is (this × multiplicand), with rounding according to the context settings.

Example online: http://tpcg.io/5axMxUQb