dotNet十进制类型是否容易受到二进制比较错误的影响? - c#

我每隔几个月偶然发现的一个错误是:

        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异常 - java

java.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…