"Formally introduced in IEEE 754-2008, it is intended for applications where it is necessary to emulate decimal rounding exactly, such as financial and tax computations."
https://en.wikipedia.org/wiki/Decimal128_floating-point_form...
"Formally introduced in IEEE 754-2008, it is intended for applications where it is necessary to emulate decimal rounding exactly, such as financial and tax computations."
https://en.wikipedia.org/wiki/Decimal128_floating-point_form...
Did you know different countries and different currencies have different rounding rules, for example for tax-related calculations? Does "IEEE decimal128" support this? Unless you can get all countries on our planet to agree on a single standard, any solution that does not allow specifying rounding rules is pretty much useless (unless you want to implement rounding yourself which tends to be very tricky -- I know because I attempted this couple of times).
Yes, of course IEEE decimal supports setting the rounding mode. The authors of the spec aren't ignorant of what's needed for financial and tax computations.
Use fe_dec_setround from ISO/IEC TR 24732, "Extension for the programming language C to support decimal floating-point arithmetic".
The modes listed at https://www.ibm.com/docs/en/zos/2.5.0?topic=functions-fe-dec... are:
FE_DEC_DOWNWARD
rounds towards minus infinity
FE_DEC_TONEAREST
rounds to nearest
FE_DEC_TOWARDZERO
rounds toward zero
FE_DEC_UPWARD
rounds toward plus infinity
FE_DEC_TONEARESTFROMZERO
rounds to nearest, ties away from zero
_FE_DEC_AWAYFROMZERO
rounds away from zero
_FE_DEC_TONEARESTTOWARDZERO
rounds to nearest, ties toward zero
_FE_DEC_PREPAREFORSHORTER
rounds to prepare for shorter precisionhttps://en.wikipedia.org/wiki/IEEE_754#Roundings_to_nearest
EDIT: apparently IEEE does not specify a "round-to-odd" for ties despite this having been used for banking in the UK :/
A classic example in invoicing is an item that is advertised for 60.00 (to the final user) VAT 10% included.
If you try making an invoice for that sum in a few programs you will find three or four way it is implemented.
Some will have 54.54+5.45=59.99, some will have 54.54+5.46=60.00, some will have 54.55+5.46=60.01 (and possibly a "discount" of 0.01), some will have 54.545+5.45=60.00, some will have 54.54545454+5.45=60,00.
My point is it's probably better to use existing, well-tested provisions than to build your own from scaled integers, to get one of those three results.
As a bonus, you might get hardware support in the future.
At the end of the day what I want (and I presume any other customer wants) is a correct invoice with the correct net, tax and total, and this will only happen when (if) the programmer understands the base issues and uses the correct library/algorithm/whatever.
Many duties are calculated based on net weight, and often the net weight per goods line is the result of a calculation, for example you're importing N items with a per-item weight of X. If you have a large number of goods items above 1kg but less than 10kg that has weight-based duties, the rounding mode can matter a lot.
None of the rounding modes mentioned captures this below/above 1kg split, so you have to do this in code anyway. Might as well do the rounding there too, to be sure some injected code doesn't mess up the expected rounding mode or similar[1].
[1]: https://irrlicht.sourceforge.io/forum/viewtopic.php?t=8773
As I understand it, one of the new things in IEEE 754 is the idea of a "context", which stores this information. This can be global, but does not need to be. With Python's decimal module it is a thread-local variable.
If you are concerned about, say, mixing thread-local and async, you can also use context methods directly, like:
>>> import decimal
>>> x = decimal.Decimal("54.1234")
>>> y = decimal.Decimal("987.340")
>>> x+y
Decimal('1041.4634')
>>> decimal.getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999,
capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero,
Overflow])
>>>
>>> c1 = decimal.Context(prec=4)
>>> c1.add(x, y)
Decimal('1041')
>>> c2 = decimal.Context(prec=5)
>>> c2.add(x, y)
Decimal('1041.5')
>>> c3 = decimal.Context(prec=5, rounding=decimal.ROUND_DOWN)
>>> c3.add(x, y)
Decimal('1041.4')
I don't know what the C or C++ API proposals are.IEEE does specify multiple rounding modes. Does it make more sense to use an existing spec, or roll your own numeric library with rounding modes?
What has changed? Or how different were your internalised rules?