C# 避免由于浮点数的二进制存储而出现意外行为的最佳方法是什么?
我最近在写一个简单的for循环,得到了一些意想不到的行为:C# 避免由于浮点数的二进制存储而出现意外行为的最佳方法是什么?,c#,.net,binary,C#,.net,Binary,我最近在写一个简单的for循环,得到了一些意想不到的行为: for(double x = 0.0; x <= 1.0; x += 0.05) { Console.WriteLine(x.ToString()); } 请注意,即使继续for循环的条件似乎包含1,也不会出现1。我意识到这是因为十进制数以二进制形式存储在内存中,也就是说,1实际上不是1,而是1.0000000000000002(根据Visual Studio中的变量watch)。所以我的问题是,避免这种意外行为的最佳方
for(double x = 0.0; x <= 1.0; x += 0.05)
{
Console.WriteLine(x.ToString());
}
请注意,即使继续for循环的条件似乎包含1,也不会出现1。我意识到这是因为十进制数以二进制形式存储在内存中,也就是说,1实际上不是1,而是1.0000000000000002(根据Visual Studio中的变量watch)。所以我的问题是,避免这种意外行为的最佳方法是什么?一种方法是使用
decimal
类型,而不是double
,但大多数系统。数学
函数仅对double
s起作用,在两者之间进行转换并不简单。不要测试double是否相等
在这里,您可以使用整数算术:
for (int i = 0; i <= 20; ++i)
{
double x = (double)i / 20.0;
Console.WriteLine(x);
}
for(int i=0;i始终自己管理舍入,不要让系统处理它
for(double x = 0.0; Math.Round(x,2,MidpointRounding.AwayFromZero) <= 1.0; x += 0.05)
{
Console.WriteLine(x.ToString());
}
for(double x=0.0;Math.Round(x,2,middpointrounding.AwayFromZero)您不能放大并使用int吗
for(int ix=0; ix < 1000; ix += 50)
{
}
for(int-ix=0;ix<1000;ix+=50)
{
}
如果需要的话,可以除以1000。但这样可以得到精确的循环行为,这被称为浮点错误,对此已有很多研究。对于您的情况,一个解决方案是定义一个错误,例如
err = .000001
并与err为1.0的范围内进行比较。这个答案对我来说似乎是最好的,尽管没有一个是理想的。我不喜欢为了避免浮点错误而对不同的东西进行迭代的想法。我希望有一种方法可以告诉编译器“合理地循环”例如,假设1.0000000000000002真的是1是安全的,但是代替我认为手工数学。()是代替。确切地说,当用小数进行数学运算时,你必须考虑有效数字。
err = .000001