-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Format strings round incorrectly #1640
Comments
For the other case, you must keep in mind that the literal given in C# source code (or parsed via Here are the values you gave and the exact representable value it is parsed to:
As you can see:
|
Thank you for the quick answer and explanation, trying to digest that since an hour... So my assumption that literal (not variables that already went through arithmetic) floating points are precise to the first few digits past decimal point is wrong, Damn you IEEE754, once again ruining my day. I should just replace every occurrence of binary floating points by |
... I mean,
... depending on how you're trying to generate values, it might not even be equivalent on the same C# process - adding some fraction, say. There's at least the ability to round-trip values if you go through This is before things like Java delegating to the hardware FPU and not enforcing strict 32/64-bit floating point (the hardware FPU may use 80 bits or more, which may subtly influence answers). |
Right, they can be incorrect with as few as one digit (e.g.
Unsure about Haskell, but Javascript numbers are explicitly spec'd to be the IEEE 754 double-precision floating-point type (i.e.
For example, you only have ~4 billion unique values for You can actually find similar problems with any representation which attempts to represent a result which could have arbitrary precision in finite space (e.g. |
(I've marked this as a |
Yeah but the rounding is different so the human output is different. Figuring that stuff out has been very frustrating 😞 |
E.g. But i have to admit that i don't understand the spec for |
Right, the spec explicitly calls out:
Yeah, I messed up. It looks to be
Ah, I see the issue. They treat I think we had a discussion about this during API review, but I don't recall the details right now. |
@tannergooding thanks again for the answers. With some more tinkering, i was able to come up with the following helper class that manages to emulate for all cases that previously produced inconsistent output between C# and JS for me. Interestingly enough, when you try to google for Since the question is answered and there's probably nothing to be changed here, feel free to close. static class JSMath
{
public static double Round(double value)
{
return Math.Floor(value + 0.5);
}
public static decimal ToFixed(double value, int digits = 0)
{
if (digits > 20)
{
throw new ArgumentException("This implementation does not support more than 20 digits", nameof(digits));
}
Span<char> chars = stackalloc char[100];
if (value.TryFormat(chars, out int written, "F21"))
{
chars = chars.Slice(0, written);
}
else
{
throw new NotImplementedException();
}
return Math.Round(Decimal.Parse(chars), digits, MidpointRounding.AwayFromZero);
}
} |
Going to close this as I believe the original question was answered. Feel free to reopen if you feel it was not or if you feel there is still work needed here. |
According to Standard numeric format strings
It only appears to do that for
F0
, usingF1
for example, the results are incomprehensible to me sharplabResults:
cc @tannergooding
The text was updated successfully, but these errors were encountered: