我在使用eval(...)实现开发一些工程规则值引擎时遇到了以下问题。
Dim first As Double = 1.1
Dim second As Double = 2.2
Dim sum As Double = first + second
If (sum = 3.3) Then
Console.WriteLine("Matched")
Else
Console.WriteLine("Not Matched")
End If
'上述条件返回false,因为sum的值是3.3000000000000003而不是3.3
看起来第15位是往返的。有人可能会对此作出更好的解释。
Math.Round(...)只有解决方案可用吗?还有其他东西我也可以尝试?
答案 0 :(得分:7)
你没有添加小数 - 你正在加倍。
并非所有双打都可以在计算机中准确表示,因此出错。我建议阅读this文章了解背景(每个计算机科学家应该知道的关于浮点算术的内容)。
使用Decimal类型,它不会遇到这些问题。
Dim first As Decimal = 1.1
Dim second As Decimal = 2.2
Dim sum As Decimal= first + second
If (sum = 3.3) Then
Console.WriteLine("Matched")
Else
Console.WriteLine("Not Matched")
End If
答案 1 :(得分:1)
这就是双号如何在PC上运行。 比较它们的最佳方法是使用这样的结构
if (Math.Abs(second - first) <= 1E-9)
Console.WriteLine("Matched")
相反,如果1E-9
您可以使用其他数字,那么这将代表比较中可能出现的错误。
答案 2 :(得分:1)
与浮点运算的等式比较总是不准确的,因为在机器中如何表示小数值。你应该有一些与你比较的epsilon值。这篇文章更全面地描述了它:
http://www.cygnus-software.com/papers/comparingfloats/Comparing%20floating%20point%20numbers.htm
编辑: Math.Round不是理想的选择,因为它为某些比较产生了错误。您最好确定一个可用于限制比较中误差量的epsilon值(基本上确定准确度)。
答案 3 :(得分:1)
double
使用浮点运算,这是近似但更有效的。如果您需要与确切的值进行比较,请改用decimal
数据类型。
答案 4 :(得分:0)
在C#,Java,Python和许多其他语言中,小数/浮点数并不完美。由于它们的表示方式(使用乘数和指数),它们通常具有不准确性。有关详细信息,请参阅http://www.yoda.arachsys.com/csharp/decimal.html。
答案 5 :(得分:0)
从文件中: http://msdn.microsoft.com/en-us/library/system.double.aspx
浮点值和丢失 精度
记住一个浮点数 只能近似一个十进制数, 并且精确度 浮点数决定了如何 准确地说,这个数字近似于a 十进制数。默认情况下,为Double value包含15位十进制数字 精度,虽然最多17 数字在内部维护。该 浮点数的精度 有几个后果:
出现两个浮点数 等于特定精度可能 因为他们的最小,所以不能比较 有效数字是不同的。
数学或比较操作 使用浮点数 如果a,可能不会产生相同的结果 使用十进制数是因为 浮点数可能不会 完全接近小数 数。
如果a,值可能不会往返 涉及浮点数。一个 据说价值是往返的 操作转换原件 浮点数到另一种形式, 逆操作转换 转换成表格 浮点数,最后一个 浮点数等于 原始浮点数。该 往返可能会失败,因为一个或 更多的最低有效数字会丢失 或在转换中更改。
另外,算术的结果 和Double的赋值操作 平台值可能略有不同 因为精度的损失 双重类型。例如, 分配文字Double的结果 值可能在32位和 64位版本的.NET Framework。 以下示例说明了这一点 字面值的差异 -4.42330604244772E-305和一个值为-4.42330604244772E-305的变量 被分配给Double变量。 注意结果 在这种情况下,Parse(String)方法可以 不会失去精确度。
答案 6 :(得分:0)
这是浮点算术的一个众所周知的问题。查看二进制编码以获取更多详细信息。
如果符合您的需要,请使用“十进制”类型。
但一般情况下,不应该使用等号将浮点值与常量浮点值进行比较。
如果不这样做,请与您想要比较的地方数量相比较(例如说它是4然后你会去(如果总和> 3.2999且总和<3.3001)