proposal-decimal icon indicating copy to clipboard operation
proposal-decimal copied to clipboard

Equality semantics and normalization

Open littledan opened this issue 6 years ago • 11 comments

Edit: this post seems to have been based on a misunderstanding of Waldemar's proposal; see https://github.com/littledan/proposal-bigdecimal/issues/11#issuecomment-557752285 for clarification.

Combining @waldemarhorwat's previous proposal with what we have in ES6 and BigInt, I'd imagine that equality semantics may be as follows:

  • === and SameValueZero compare the normalized values
  • ==, <, etc can compare BigDecimals to other numeric types, according to their mathematical values (following BigInt)
  • SameValue/Object.is compares according to the representation of BigDecimal (just one NaN, but differentiating trailing zeroes)

Does anyone have concerns with these semantics?

littledan avatar Nov 13 '19 18:11 littledan

What's the use case for differentiation of trailing zeros in Object.is? It may be more useful to provide a function which returns the number of decimal places to compare for equivalence based on trailing zeros.

chicoxyzzy avatar Nov 13 '19 20:11 chicoxyzzy

That library function sounds interesting. Maybe you could explain the semantics and motivation a bit further in #14 ?

We have a general invariant in JavaScript, that if two values are Same value/Object.is, then they are totally indistinguishable, and could be thought of as "the same value". So then we wouldn't be able to make that library function work if so.

littledan avatar Nov 13 '19 22:11 littledan

In my intuition Object.is(0m, .0m) should return true or we should have Math.signbit to distinguish 0m and -0m (but consider 0m and .0m as equal) using n1 === n2 && Math.signbit(n1) === Math.signbit(n2). Math.sign is kind of broken because Math.sign(-0) === Math.sign(0).

chicoxyzzy avatar Nov 14 '19 03:11 chicoxyzzy

On the other hand, if there will be no -0m, then it could be fine.

Decimal.js and friends do have -0. Should we create a separate issue about -0 since #9 is about non-finite values only? Negative could be useful to indicate last stock price change direction for example, though it's not a common case in my practice. Also it could be confusing if BigDecimal will have -0m when BigInt doesn't have -0n

chicoxyzzy avatar Nov 14 '19 05:11 chicoxyzzy

Most use cases won't care or need to think about precision.

It's fine if a BigDecimal value can carry precision information, but this shouldn't be considered on any common paths (===, ==, Object.is, etc).

ljharb avatar Nov 17 '19 02:11 ljharb

I think it'd be a pretty big change in how JS works in general if precision were distinguishable according to some library function, but the two values are Object.is. Could you say more about why they should be indistinguishable along this path, and what this would mean for equality in general?

littledan avatar Nov 17 '19 09:11 littledan

I don't think I agree that most use cases won't care about precision. For example, trailing zeroes are useful in the money case, which I think will be extremely common. $2.5 is not really semantically meaningful, and $2.50 is.

@ljharb If you want to argue that BigDecimal should always be normalized, please file an issue arguing that; this issue is about how to handle equality on the basis of a data model which does support trailing zeros.

littledan avatar Nov 17 '19 09:11 littledan

My argument imo applies to both; i think it would be very surprising if the same number with different precisions were sometimes distinguishable and sometimes not. Also, this isn’t a proposal for currency or money as i understand it, so the semantic meaning of $ and $2.50 don’t apply to this proposal.

In other words, if the proposal is going to consider 2.5 and 2.50 to be different, then I think so should ===, ==, toString, Object.is, etc.

ljharb avatar Nov 17 '19 19:11 ljharb

@ljharb It would be helpful if you could explain where you disagree with @waldemarhorwat's previous arguments, in addition to stating your conclusion.

littledan avatar Nov 17 '19 20:11 littledan

@littledan that's a long argument and it seems to require a lot of context, so i'm not sure what specifically i should be disagreeing with. The "Should trailing zeroes be printed when doing toString on decimal values?" question seems to assume that 0m would toString to 0 - but I don't think that's necessarily a foregone conclusion just because 0n toStrings to 0.

I do agree that trailing zeroes should not be printed, though, which seems to suggest that 5.00m and 5m would be ===. Can you help me understand what in that linked email suggests that trailing zeroes/precision should be preserved?

ljharb avatar Nov 18 '19 08:11 ljharb

I strongly feel that IEEE decimal trailing zeros should not be distinguishable. You may say that someone wants to distinguish 5.00m from 5.0m, but the real trouble starts when the precision is less than the number of digits in an integer. You'd need to distinguish 1000m from the result of 2000m/2m; the latter would have one less significant digit than the former and couldn't even be printed as an integer if you wanted to retain the precision in printed form. This would get weird very quickly.

waldemarhorwat avatar Nov 23 '19 01:11 waldemarhorwat