我每隔几个月偶然发现的一个错误是:
double x = 19.08;
double y = 2.01;
double result = 21.09;
if (x + y == result)
{
MessageBox.Show("x equals y");
}
else
{
MessageBox.Show("that shouldn't happen!"); // <-- this code fires
}
您应该假设代码显示“ x等于y”,但事实并非如此。
简短的解释是,用二进制数字表示的小数位不适合双精度。
例:
2.625看起来像:
10.101
因为
1-------0-------1---------0----------1
1 * 2 + 0 * 1 + 1 * 0.5 + 0 * 0.25 + 1 * 0,125 = 2.65
并且某些值(如19.08加2.01的结果)不能用双精度位表示。
一种解决方案是使用常量:
double x = 19.08;
double y = 2.01;
double result = 21.09;
double EPSILON = 10E-10;
if ( x + y - result < EPSILON )
{
MessageBox.Show("x equals y"); // <-- this code fires
}
else
{
MessageBox.Show("that shouldn't happen!");
}
如果我在第一个示例中使用十进制而不是双精度,则结果为“ x等于y”。
但是我在问自己,这是否是因为“十进制”类型不易受此行为的影响,或者仅在这种情况下有效,因为这些值“适合” 128位。
也许有人比使用常数有更好的解决方案?
顺便说一句。这不是dotNet / C#问题,它发生在我认为的大多数编程语言中。
参考方案
只要您将数值保持在适当范围内的自然十进制值之内,十进制就将是准确的。因此,例如,如果仅进行加法和减法,而没有做任何会使所需数字范围过大的事情(将非常大的数字添加到非常小的数字),则最终会得到可比较的结果。乘法也可能还可以,但是我怀疑这样会更容易出错。
一旦开始除法,问题就出在这里-尤其是如果您开始除以包含2或5以外的质数的数字。
底线:在某些情况下是安全的,但是您确实需要对要执行的操作有一个很好的了解。
请注意,并不是小数位数的128位在这里为您提供帮助-而是数字的表示形式为浮点小数点值,而不是浮点二进制点值。有关更多信息,请参见我在.NET binary floating point和decimal floating point上的文章。
当回复有时是一个对象有时是一个数组时,如何在使用改造时解析JSON回复? - java我正在使用Retrofit来获取JSON答复。这是我实施的一部分-@GET("/api/report/list") Observable<Bills> listBill(@Query("employee_id") String employeeID); 而条例草案类是-public static class…
如何在ASP.NET Page_Load事件中识别RadButton启动回发的原因? - c#在我的ASP.NET页的Page_Load中,我试图确定某个按钮是否已单击并尝试回发:if (Page.IsPostBack) { if (Request.Params.Get("__EVENTARGUMENT") == "doStuff") doSomething(); } doStuff是标记内的JavaScrip…
java.net.URI.create异常 - javajava.net.URI.create("http://adserver.adtech.de/adlink|3.0") 抛出java.net.URISyntaxException: Illegal character in path at index 32: http://adserver.adtech.de/adlink|3.0 虽然n…
如何从JSON文件反序列化.NET Core中封装的对象表? - c#我想从外部API检索足球联赛的集合。来自服务器的响应如下所示:{ "api": { "results": 1496, "leagues": [ { "league_id": 1, ..... 返回的对象由“ api”字段组成,其中包含“结果”和“联盟”。我想反序列化代码并将其映射…
asp.net:treeview-显示文本框是否选中? - c#我需要向用户显示字符串列表。用户可以选择多个字符串。如果选择了一组特定的字符串,则每个字符串旁边都会出现一个文本框。我想做的是向用户显示一个TREEVIEW,每个节点都是字符串之一。他们将通过选中复选框来选择所需的每个字符串。问题:如果用户选择特定的复选框,则我需要一个文本框来显示用户的GET输入。问题:如何从用户使用树形视图获取字符串输入? 参考方案 Tr…