Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Equality semantics and normalization #11

Open
littledan opened this issue Nov 13, 2019 · 11 comments
Open

Equality semantics and normalization #11

littledan opened this issue Nov 13, 2019 · 11 comments

Comments

@littledan
Copy link
Member

littledan commented Nov 13, 2019

Edit: this post seems to have been based on a misunderstanding of Waldemar's proposal; see #11 (comment) 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?

@chicoxyzzy
Copy link
Member

chicoxyzzy commented Nov 13, 2019

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.

@littledan
Copy link
Member Author

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.

@chicoxyzzy
Copy link
Member

chicoxyzzy commented Nov 14, 2019

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
Copy link
Member

chicoxyzzy commented Nov 14, 2019

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

@ljharb
Copy link
Member

ljharb commented Nov 17, 2019

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).

@littledan
Copy link
Member Author

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
Copy link
Member Author

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.

@ljharb
Copy link
Member

ljharb commented Nov 17, 2019

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.

@littledan
Copy link
Member Author

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

@ljharb
Copy link
Member

ljharb commented Nov 18, 2019

@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?

@waldemarhorwat
Copy link

waldemarhorwat commented Nov 23, 2019

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants