C# rounding differently depending on platform?

后端 未结 4 1646
花落未央
花落未央 2020-12-01 18:29

I have this tiny piece of code

double s = -2.6114289999999998;
double s7 = Math.Round(s, 7);
double s5 = Math.Round(s, 5);
double s6 = Math.Round(s, 6);
         


        
4条回答
  •  情书的邮戳
    2020-12-01 19:06

    On x64, the SSE2 FPU is used and on x86 the x87 FPU is used.

    It is possible (although not advised) to change the x87 precision to be the same as the SSE2 precision (i.e., use lower precision).

    You can do that via the _controlfp() API.

    The following program demonstrates. Run this program in x86 mode and you'll see how the use of _controlfp(0x00030000, 0x00020000) causes the output to change to be similar to (but not quite the same!) as the x64 version:

    using System;
    using System.Runtime.InteropServices;
    
    namespace ConsoleApp3
    {
        class Program
        {
            static void Main()
            {
                double s = -2.6114289999999998;
    
                Console.WriteLine(Math.Round(s, 7).ToString("R")); // -2.611429
    
                if (!Environment.Is64BitProcess)
                    _controlfp(0x00030000, 0x00020000);
    
                Console.WriteLine(Math.Round(s, 7).ToString("R")); // -2.61142897605896
            }
    
            [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
            static extern uint _controlfp(uint newcw, uint mask);
        }
    }
    

    However, you should not mess around with the FPU in this way (and if you do, you should revert to the previous setting asap).

提交回复
热议问题