Runtime: Math.Max/Min methods work differently in .Net Core 3 and Net Framework

Created on 29 Jan 2019  路  11Comments  路  Source: dotnet/runtime

The Math.Max and Math.Min methods with double arguments work differently in .Net Core 3 and Net Framework:

Math.Max(double.NaN, 0d) returns 0 in .Net Core 3

Math.Max(double.NaN, 0d) returns double.NaN in Net Framework

Environment data

dotnet --info output:
.NET Core SDK (reflecting any global.json):
Version: 3.0.100-preview-010124
Commit: 41a73b60f2

Runtime Environment:
OS Name: Windows
OS Version: 10.0.17763
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk3.0.100-preview-010124\

Host (useful for support):
Version: 3.0.0-preview1-26919-02
Commit: 9ea8c26816

.NET Core SDKs installed:
2.1.500 [C:\Program Files\dotnet\sdk]
2.1.600-preview-009426 [C:\Program Files\dotnet\sdk]
2.1.600-preview-009472 [C:\Program Files\dotnet\sdk]
3.0.100-alpha1-009616 [C:\Program Files\dotnet\sdk]
3.0.100-preview-009812 [C:\Program Files\dotnet\sdk]
3.0.100-preview-010124 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
Microsoft.AspNetCore.All 2.1.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.All 3.0.0-alpha1-10062 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.0-alpha1-10062 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.0-preview-18579-0056 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.0.0-preview-19067-0383 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.DesktopUI.App 3.0.0-alpha-26829-8 [C:\Program Files\dotnet\shared\Microsoft.DesktopUI.App]
Microsoft.NETCore.App 2.1.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 2.1.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.0-preview-27122-01 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.0-preview-27316-4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 3.0.0-preview1-26919-02 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.0.0-alpha-27128-4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 3.0.0-preview-27316-2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

To install additional .NET Core runtimes or SDKs:
https://aka.ms/dotnet-download

area-System.Numerics documentation

Most helpful comment

We聽faced this issue while porting the DevExpress WPF Controls suite to Net Core 3 - some of our tests failed. Of course, we can modify our code and re-write our tests (in fact, we have already done it). However, in a general case, such differences between Net Core 3 and Net Framework will definitely complicate聽cross-platform development. If an application or a component was developed under Net Framework and was not specifically modified to work with Net Core 3 (or developers didn't know about such changes), it will work incorrectly in the compatibility Net Core 3 mode.聽

I would highly appreciate if you share a full list of such differences (incompatibilities) between Net Core聽and聽Net Framework so we can take them into account while porting our components.

All 11 comments

/cc @tannergooding

This change was by design in order to ensure that the functions had the appropriate IEEE 754 compliant behavior.

Most IEEE 754 operations indicate that the NaN payload should be preserved. However, minNum and maxNum, in particular, require that the other number be returned if one is NaN.

minNum(x, y) is the canonicalized number x if x < y, y if y < x, the canonicalized number if one operand is a number and the other a quiet NaN. Otherwise it is either x or y, canonicalized (this means results might differ among implementations). When either x or y is a signalingNaN, then the result is according to 6.2.

Closing this as "by-design" as this was fixed as part of the IEEE 754 compliance work.

Feel free to leave any additional comments or re-open if you feel this needs further discussion.

Thank you for the explanation. By the way, the documentaion still says that the double.NaN value is returned in a such cases:
2019-01-30_09-47-12

It would be a huge breaking change in scenarios, when WinForms and WPF controls can be used as is in .Net Core 3 applications. Are you planning to add some sort of a feature toggle to restore the previous behavior?

By the way, the documentaion still says that the double.NaN value is returned in a such cases

Thanks for catching this. I've logged a bug tracking updating this here: https://github.com/dotnet/dotnet-api-docs/issues/1736

It would be a huge breaking change in scenarios, when WinForms and WPF controls can be used as is in .Net Core 3 applications. Are you planning to add some sort of a feature toggle to restore the previous behavior?

We normally only add a toggle after there has been enough feedback indicating that it is necessary/worthwhile. Do you have some more data on existing WinForms/WPF code that would hit an issue due to this?

We聽faced this issue while porting the DevExpress WPF Controls suite to Net Core 3 - some of our tests failed. Of course, we can modify our code and re-write our tests (in fact, we have already done it). However, in a general case, such differences between Net Core 3 and Net Framework will definitely complicate聽cross-platform development. If an application or a component was developed under Net Framework and was not specifically modified to work with Net Core 3 (or developers didn't know about such changes), it will work incorrectly in the compatibility Net Core 3 mode.聽

I would highly appreciate if you share a full list of such differences (incompatibilities) between Net Core聽and聽Net Framework so we can take them into account while porting our components.

I would highly appreciate if you share a full list of such differences (incompatibilities) between Net Core and Net Framework so we can take them into account while porting our components.

I found other "incompatibilities" or different defaults between netfx/netcoreapp I wonder if could be useful have an official doc with diff(organized for namespace/class/member), maybe in a matter of months could be complete.

/cc @jkotas @danmosemsft @stephentoub

I believe that it would be very helpful for developers

I think it would be best to have such differences here: https://github.com/dotnet/platform-compat ... @terrajobst thoughts?

This was reverted due to the WPF scenario and it now preserves the NaN once again. We will likely be adding new overloads that don't preserve the NaN in the future.

Closing since this also means we don't have anything that needs to be documented.

Was this page helpful?
0 / 5 - 0 ratings