-
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
Math.Round(value, digits, mode) does not return the correct result #1643
Comments
An example of where this fails is: The nearest representable value with 2 digits is: For this case, the |
I need to dig up the notes on |
Merge from dotnet/runtime
For |
We would like to fix this at some point, but it is a non-trivial issue, so this is not guaranteed to happen for .NET 8. Moved to Future for now. |
Hi Guys, hope all's well! Curious to know when you're going to get round to this issue? I've recently moved an application to Net 8 and ran into this. |
@DasNaughtie There's been no change in behavior since .NET Framework, this is tracking making an eventual breaking change to the behavior to fix it to do the correct thing. Could you elaborate on what it is you're seeing? |
After spending a number of hours trying to get to the bottom of this the problem seems to exist with EF core - I'm running a linq query that is correct in VS 2022 but when I execute it profiler is showing me completely different values! 0.005 is being converted to 1 and 0.0004 is being converted to 0.0004000000000000000191686944095437183932517655 |
You're observing the raw underlying value in this case.
There was notably a bug fix introduced in .NET Core 3.0: https://devblogs.microsoft.com/dotnet/floating-point-parsing-and-formatting-improvements-in-net-core-3-0/, which is that we changed to ensuring that Because the literal you typed is not necessarily the exact underlying value, this can lead to some weird rounding edge cases. For example, |
So in summary MS has taken something that worked perfectly fine and screwed it up to the point where I have to use a profiler to see the results of my unit tests because the UI doesn't represent the truth? How do you get away with this? It's taken months of work to get this solution and the multiple others into .Net only to find the ORM doesn't support the basic querying? This is the Linq statement that is now broken:
That is as basic as it gets and EF Core doesn't support this scenario because of a float or double? |
Nothing has changed, the behavior of This issue is tracking a planned future break to ensure that correct results are computed as there are known cases that they have never been correct, and thus ensuring As for how float/double work, this is how IEEE 754 floating-point numbers work in all languages. Whether it is C, C++, Java, Swift, Rust, Go, Javascript, C#, VB, F#, etc. It is not unique to .NET, it is not unique to Microsoft, it is simply part of programming with such numbers. If you are doing something like working with currency, you should likely be using a |
true for whats being discussed, but it looks like the discussion is passing over whats broken in the first place
thats probably whats causing issues, and its unlikely to be related to this issue or floating point representation at all further investigation should probably focus at what happens between EF Core and the SQL statement generation |
That's why I said "As such, there is likely some other cause of the break in your code that is not related to Math.Round.". That is, there is likely something else broken in the code and not enough context to help root cause the problem. It is likely in how |
I don't know what else to say. I accept this is nothing to do with Math.Round but find it difficult to see an issue with the code. I'll park this here and update the other issue I've created. Thanks for your patience. |
The
Math.Round(value, digits, mode)
code returns a close, but not correct result most of the time.The root problem is that the algorithm tries to follow normal mathematical rules to produce the result. However, due to the variable precision in IEEE floating-point numbers, this ultimately causes it to produce a close, but generally incorrect result most of the time and causes it to not accept inputs above a certain range. For example, you can't round
double.MaxValue
and the larger the input is, the more inaccurate the rounding will be.These functions should be rewritten to be IEEE compliant and to accept any valid finite floating-point input.
The text was updated successfully, but these errors were encountered: