发行方式采用双precision甚至浮点型变量 [英] release mode uses double precision even for float variables

查看:150
本文介绍了发行方式采用双precision甚至浮点型变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的算法计算小量对于单precision 浮点运算。它被认为是围绕1.1921e-007的东西。这里是code:

My algorithm is calculating the epsilon for single precision floating point arithmetic. It is supposed to be something around 1.1921e-007. Here is the code:

static void Main(string[] args) {
    // start with some small magic number
    float a = 0.000000000000000013877787807814457f;
    for (; ; ) {
        // add the small a to 1
        float temp = 1f + a;
        // break, if a + 1 really is > '1'
        if (temp - 1f != 0f) break;
        // otherwise a is too small -> increase it
        a *= 2f;
        Console.Out.WriteLine("current increment: " + a); 
    }
    Console.Out.WriteLine("Found epsilon: " + a); 
    Console.ReadKey(); 
}

在调试模式下,它提供了以下合理的输出(略):

In debug mode, it gives the following reasonable output (abbreviated):

current increment: 2,775558E-17
current increment: 5,551115E-17
...
current increment: 2,980232E-08
current increment: 5,960464E-08
current increment: 1,192093E-07
Found epsilon: 1,192093E-07

(!不管有/无优化)

然而,当切换到释放模式中,code给出以下结果:

However, when switching to release mode (no matter with/ Without optimization!), the code gives the following result:

current increment: 2,775558E-17
current increment: 5,551115E-17
current increment: 1,110223E-16
current increment: 2,220446E-16
Found epsilon: 2,220446E-16

这相当于为双precision值。所以我认为,一些优化导致计算要在双值来实现。当然结果是错在这种情况下!

which corresponds to the value for double precision. So I assume, some optimizations cause the computations to be done on double values. Of course the result is wrong in this case!

另外:这只是发生,如果针对的 86 发布项目的选项。还是那句话:开启/关闭优化无所谓。我在64位WIN7,VS 2010旗舰版,面向.NET 4.0。

Also: this happens only, if targeting X86 Release in the project options. Again: optimization on/off does not matter. I am on 64 bit WIN7, VS 2010 Ultimate, targeting .NET 4.0.

什么可能导致这种行为?一些WOW的问题?如何绕过它以可靠的方式?如何prevent的CLR生成code,这使得使用双precision,而不是单一的precision计算?

What might cause that behaviour? Some WOW issue? How to get around it in a reliable way? How to prevent the CLR to generate code which makes use of double precision instead of single precision calculations?

请注意:切换到任何CPU,甚至X64作为目标平台是没有选项 - 即使不出现问题就在这里。但是,我们有一些本机库,在不同版本的32/64位。因此,目标必须是具体的。

Note: switching to "Any CPU" or even "X64" as platform target is no option - even if the problem does not occur here. But we have some native libraries, in different versions for 32/64 bit. So the target must be specific.

推荐答案

由于在评论中讨论,这是预期。它可以是侧阶梯通过除去了JIT的保持值中的寄存器(这将是比实际值较宽)能力 - 通过迫使它下降到一个场(其已明确定义的大小):

As discussed in the comments, this is expected. It can be side-stepped by removing the JIT's ability to keep the value in a register (which will be wider than the actual value) - by forcing it down to a field (which has clearly-defined size):

class WorkingContext
{ 
    public float Value; // you'll excuse me a public field here, I trust
    public override string ToString()
    {
        return Value.ToString();
    }
}
static void Main()
{
    // start with some small magic number
    WorkingContext a = new WorkingContext(), temp = new WorkingContext();
    a.Value = 0.000000000000000013877787807814457f;
    for (; ; )
    {
        // add the small a to 1
        temp.Value = 1f + a.Value;
        // break, if a + 1 really is > '1'
        if (temp.Value - 1f != 0f) break;
        // otherwise a is too small -> increase it
        a.Value *= 2f;
        Console.Out.WriteLine("current increment: " + a);
    }
    Console.Out.WriteLine("Found epsilon: " + a);
    Console.ReadKey();
}

有趣的是,我试图与一个结构第一,但JIT是能够看到过去我作弊(presumably因为它是所有在栈上)。

Interestingly, I tried this with a struct first, but the JIT was able to see past my cheating (presumably because it is all on the stack).

这篇关于发行方式采用双precision甚至浮点型变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆