C# – Inconsistent math operation result on 32-bit and 64-bit

The x86 instruction set has tricky floating point consistency issues due the way the FPU works. Internal calculations are performed with more significant bits than can be stored in a double, causing truncation when the number is flushed from the FPU stack to memory.

That got fixed in the x64 JIT compiler, it uses SSE instructions, the SSE registers have the same size as a double.

This is going to byte you when your calculations test the boundaries of floating point accuracy and range. You never want to get close to needing more than 15 significant digits, you never want to get close to 10E308 or 10E-308. You certainly never want to square the largest representable value. This is never a real problem, numbers that represent physical quantities don’t get close.

Use this opportunity to find out what is wrong with your calculations. It is very important that you run the same operating system and hardware that your customer is using, high time that you get the machines needed to do so. Shipping code that is only tested on x86 machine is not tested.

The Q&D fix is Project + Properties, Compile tab, Platform Target = x86.


Fwiw, the bad result on x86 is caused by a bug in the JIT compiler. It generates this code:

      double r = Math.Sqrt(v1 * v1);
00000006  fld         dword ptr ds:[009D1578h] 
0000000c  fsqrt            
0000000e  fstp        qword ptr [ebp-8] 

The fmul instruction is missing, removed by the code optimizer in release mode. No doubt triggered by it seeing the value at double.MaxValue. That’s a bug, you can report it at connect.microsoft.com. Pretty sure they’re not going to fix it though.

Leave a Comment