我的老板今天报告了我的错误,因为只要他想指定低于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
发生了什么事?
答案 0 :(得分:1)
这是因为0.04不能完全表示为float
- 结果也不能乘以100.结果非常小于4,所以投射到int截断它。
基本上,如果您想使用十进制精确表示的数字,则应使用decimal
类型而不是float
或double
。有关详细信息,请参阅decimal floating point和binary 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