Open sffc opened 1 year ago
I didn't go this deep but it would be interesting to see how the prior art handles the "middle ground" proposal suggested in the slide deck, namely whether lessThan
and equals
pay attention to the trailing zeros.
compareTo
uses mathematical value and doesn't care about trailing zeroes (https://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html#compareTo-java.math.BigDecimal-).equals
cares about trailing zeroes (https://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html#equals-java.lang.Object-).toString
preserves trailing zeroes (https://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html#toString--).Trailing zeros do not affect the value of a Decimal number in arithmetic or comparison operations.
ToString
can expose trailing zeroes.
However, trailing zeros might be revealed by the ToString method if an appropriate format string is applied.
>>> Decimal("1.20") < Decimal("1.2") False >>> Decimal("1.20") == Decimal("1.2") True
compare
and compare_total
methods.compare
is like the comparison operators, compares by mathematical value only (https://docs.python.org/3/library/decimal.html#decimal.Decimal.compare).compare_total
imposes a total ordering on Decimal
values and takes trailing zeroes into account when comparing values (https://docs.python.org/3/library/decimal.html#decimal.Decimal.compare_total).str
(Python's toString
) preserves trailing zeroes.
>>> str(Decimal("1.20")) '1.20'
So in conclusion, Java, C# and Python's behavior is closest to the "middle ground" proposal. The primary comparison operators care only about the mathematical value and ignore trailing zeroes. The string conversion exposes trailing zeroes. On the other hand, Ruby adopts the always-normalize strategy.
On top of that, Python offers a compare_total
method that can provide a total ordering of the decimal values by taking into account trailing zeroes and Java's equals
method compares both value and scale, so that BigDecimal
s which are equal according to equals
are indistinguishable using the other BigDecimal
methods.
In Temporal we had similar questions about what fields to consider in .compare
and .equals
; what we landed on was .compare
being more lenient and .equals
being more strict, meaning .compare() == 0
doesn't imply .equals()
.
https://github.com/tc39/proposal-temporal/issues/523
@ljharb @ptomato
Just to update this discussion with the status quo:
compare
method that works on all decimal values (even NaNs and infinities) and compares the full decimal data, allowing the programmer to distinguish mathematically equal but distinct-in-Decimal128-world values. The range will be { -1, 0, 1, NaN } (...the latter because of NaN pollution).It looks like Python has a compare_total
function
$ python3
Python 3.11.8 (main, May 26 2024, 00:40:16) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from decimal import Decimal
>>> Decimal("1.00") == Decimal("1.0")
True
>>> Decimal("1.00") < Decimal("1.0")
False
>>> Decimal("1.00").compare_total(Decimal("1.0"))
Decimal('-1')
The answer for Postgresql is "NO", not "YES". Postgres does not store the precision together with the number, and instead it's part of the type of the column (so, there is no difference between trying to store 12.0 or 12.00 in any given column).
This week's slides discuss precedent for decimals from other programming languages. I did some quick research on the listed programming languages to see if they support trailing zeros.
Java: YES
https://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html
C#: YES
https://learn.microsoft.com/en-us/dotnet/api/system.decimal?view=net-8.0
Python: YES
https://docs.python.org/3/library/decimal.html
Ruby: Wasn't able to determine for sure in the short amount of time I took to research, but I think it does not support them. Ruby defines decimals as: "arbitrary-precision floating point decimal arithmetic". When I play with them in
irb
I can't seem to get a trailing zero to roundtrip.Postgresql: YES
https://www.postgresql.org/docs/8.1/datatype.html https://stackoverflow.com/questions/26920157/postgresql-adds-trailing-zeros-to-numeric
@jessealama