为什么(int)(float.Parse(“0.04”,System.Globalization.CultureInfo.InvariantCulture)* 100)等于3

时间:2012-02-13 19:19:49

标签: c# .net

我的老板今天报告了我的错误,因为只要他想指定低于5%的值,我的配置就会减少。我知道我可以将我的数字转换为int来解决我的问题,但是我不明白为什么会出现这个问题。

我有一个值为“0.04”的app.config文件和一个带有float属性的配置节。读取该部分时,检索到的浮点值为0.04,这很好。我想把这个值放在一个接受整数值的Windows窗体TrackBar中,所以我将我的值乘以100并将其转换为int。由于某种原因,结果不是4,但它是3.你可以这样测试:

Console.WriteLine((int)(float.Parse("0.04", System.Globalization.CultureInfo.InvariantCulture) * 100)); // 3

发生了什么事?

4 个答案:

答案 0 :(得分:1)

这是因为0.04不能完全表示为float - 结果也不能乘以100.结果非常小于4,所以投射到int截断它。

基本上,如果您想使用十进制精确表示的数字,则应使用decimal类型而不是floatdouble。有关详细信息,请参阅decimal floating pointbinary floating point上的文章。

编辑:这里有一些更有趣的东西,实际上......特别是,如果你首先将结果分配给局部变量,那就会改变结果:

using System;
using System.Globalization;

class Test
{
    static void Main()
    {
        // Assign first, then multiply and assign back, then print
        float f = Foo();
        f *= 100;
        Console.WriteLine((int) f); // Prints 4

        // Assign once, then multiply within the expression...
        f = Foo();
        Console.WriteLine((int) (f * 100)); // Prints 4

        Console.WriteLine((int) (Foo() * 100)); // Prints 3
    }

    // No need to do parsing here. We just need to get the results from a method
    static float Foo()
    {
        return 0.04f;
    }
}

我不确定这里到底发生了什么,但0.04f的确切值是:

0.039999999105930328369140625

...所以它确实有意义不打印4,可能。

如果使用double算术而不是float执行乘以100, 可以强制结果为3:

f = Foo();
Console.WriteLine((int) ((double)f * 100)); // Prints 3

...但我不清楚为什么原始版本会发生这种情况,因为float.Parse会返回float,而不是double。猜测结果是,结果保留在寄存器中,后续乘法是使用double算术执行的(根据规范有效),但这肯定是一个令人惊讶的差异。

答案 1 :(得分:0)

这是因为浮点值更像是0.039999999999;因此,您将类似3.99999999999的值转换为int,产生3。

您可以通过舍入来解决问题:

Console.WriteLine((int)Math.Round(float.Parse("0.04", System.Globalization.CultureInfo.InvariantCulture) * 100));

答案 2 :(得分:0)

实际上不是4而是3,99999以及许多其他数字。做这样的事情:

(int)(float.Parse("0.04") * 100.0 + 0.5)

Casting to float就像一个floor操作符,因为它不是4,它被截断为3。

答案 3 :(得分:0)

作为一个浮点数0.04 * 100可能表示为3.9999999999,并且转换为int只是截断它,所以这就是为什么哟看到3