开发者

Problem running x86-target assembly in Win7

开发者 https://www.devze.com 2023-04-03 23:57 出处:网络
I have a C# project configured for x86 platform target. The application works perfectly in WinXP, but it gets problem in Win7. I am using VS2008.

I have a C# project configured for x86 platform target. The application works perfectly in WinXP, but it gets problem in Win7. I am using VS2008.

Please see the test code below (the problem: it prints 0 in WinXP and 1 in Win7).

Note: the code also works fine in Win7 if running on Debug mode or adding a line of trace.

Please advise, thanks!

using System;
using System.Windows.Forms;

namespace Hello
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            //The problem: it shows "0" in WinXP, and shows "1" in Win7
            MessageBox.Show(Test.GetValue().ToString());

            Environment.Exit(0);
        }
    }

    public class Test
    {
        static int a = 0;

        static public float GetValue()
        {
            float b = 0.8149883f;

            flo开发者_开发技巧at x = (696f / b + a);

            //Note: it returns 0 if uncomments the line below, otherwise it returns 1 
            //MessageBox.Show("hello");

            return (x - (int)x);
        }
    }
}


In addition to the point that @CodeInChaos makes, floating point calculations vary on different hardware architectures. That's simply the nature of floating point units. Even two FP units that both adhere to IEEE754 can give different results to each other. Obviously the differences will be vanishingly small. So even without any JIT differences, you may see different results on a different machine.

In your case you simply need to compare floating point values in a different way. Instead of testing for exact equality, test for equality up to a small tolerance, i.e. abs(a-b)<epsilon where epsilon is a small number.


The JIT compiler is free to optimize floating point even if that slightly changes the result. You simply can't expect the results to be the same on all platforms.

Sometimes it interprets your 853.9999... as 854.0 sometimes it keeps it as 853.9999.... This is because on some platforms the intermediate results are calculated with higher precision. And at which point it gets degraded to float varies. In your example it looks like the message box forces the compiler to store the value outside of the FPU at which point it gets converted to 32 bit float.

Related question: Is floating-point math consistent in C#? Can it be?

If performance isn't too important you can simply use Decimal and get deterministic results.


Note that if you use double, the results work as expected.

If you take the result of the division and look at the representation in IEEE-754 for both float and double representation, you'll see why:

853.99998993850586566702859415282

As float: 854.00000

As double: 853.99998993850590

(From http://babbage.cs.qc.edu/courses/cs341/IEEE-754.html)

Why you are seeing different results between debug and release, I'm not sure - I don't see that in VS2010.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号