【问题标题】:What's the best way to compare Double and Int?比较 Double 和 Int 的最佳方法是什么?
【发布时间】:2009-10-30 14:24:17
【问题描述】:

以下 C# 代码不起作用:

int iValue = 0;
double dValue = 0.0;

bool isEqual = iValue.Equals(dValue);

那么问题来了:比较 Double 和 Int 的最佳方法是什么?

【问题讨论】:

标签: c# double int equals


【解决方案1】:

你真的不能以幼稚的方式比较浮点和整数值;特别是,因为有经典的floating pointrepresentation challenges。您可以做的是从另一个中减去一个,看看它们之间的差异是否小于您关心的某个精度,如下所示:

int iValue = 0;
double dValue = 0.0;

var diff = Math.Abs(dvalue - iValue);
if( diff < 0.0000001 ) // need some min threshold to compare floating points
   return true; // items equal

您确实必须自己定义equality 对您意味着什么。例如,您可能希望浮点值向最接近的整数舍入,这样 3.999999981 将“等于”4。或者您可能希望截断该值,因此它实际上是 3。这完全取决于您'正在努力实现。

编辑:请注意,我选择 0.0000001 作为示例阈值...您需要自己决定什么精度足以进行比较。只要意识到你需要在double 的正常表示范围内,我相信它被定义为Double.Epsilon

【讨论】:

  • 这是我提到的问题的一个很好的解决方案。为了获得更高的准确性(仅在必要时),请仅使用整数,正如我在回答中所建议的那样。
  • 与系统定义的常量 epsilon(参见此处msdn.microsoft.com/en-us/library/system.double.epsilon.aspx)而不是像 0.0000001 这样的硬编码值进行比较会更好吗?注意我从来没有编写过 C#(只是 C++),但我认为同样的原则也适用
  • 我在回答的编辑中提到了这一点。 Epsilon 可能是也可能不是一个好选择,具体取决于 OP 在其代码中关心的精度。
  • Double.Epsilon 只有在减去 0 和 1 之间的值时才有用,因为它是“大于零的最小正 Double 值”。由于double 值的间距不均匀,并且它们的距离随着它们的大小而增加,如果你减去两个值,你将永远不会得到 Double.Epsilon 周围的东西。
  • @Johannes:这是一个很好的观点。对于非常大的正/负值,代码在评估相等性时需要更加“放松”。
【解决方案2】:

在任何语言中比较整数和浮点数是否相等是一个非常糟糕的主意。它适用于非常简单的情况,但是在您进行任何数学运算之后,程序执行您希望它执行的操作的可能性会大大降低。

这与浮点数在二进制数字系统中的存储方式有关。

如果您非常确定要使用它,请创建一个类以使用分数创建您自己的数字。使用一个 int 来维护整数,使用另一个 int 来维护分数。

【讨论】:

    【解决方案3】:

    这真的取决于你认为什么是“平等的”。如果您希望您的比较在且仅当 double 与整数值精确匹配(即没有小数部分)时才返回 true,您应该将您的 int 转换为 double 以进行比较:

    bool isEqual = (double)iValue == dValue;
    

    如果将 1.1 之类的值视为等于 1,则可以将双精度数转换为 int(如果您想完全忽略小数部分),或者如果您希望 1.9 等于 2,则将双精度数舍入。

    【讨论】:

    • 小心舍入,不过。当 2.5 轮到 2 时,许多人似乎感到惊讶。
    • @Joey 如果三个内置代码不能满足您的需求,编写自己的舍入代码以获得您想要的行为非常简单。
    【解决方案4】:

    如今,几乎唯一一次应该比较 doubleintegerlong 类型的值以实现严格相等是由于某种原因,一个人被卡住存储或传递整数作为浮点数-点值,以后需要将它们转换回来。在大多数情况下,通过将整数类型转换为double,然后比较该转换的结果,可以最容易地完成这种转换。请注意,如果数字超出范围 ±252,则从 longdouble 的转换可能不精确。尽管如此,在 64 位 long 可用之前的日子里,double 是一种方便的存储类型,用于存储对于 32 位 int 来说太大但小到足以由 double 处理的整数。

    请注意,如果double 的标称值与long 值不完全匹配,但代表最接近的值,则将long 转换为double 然后进行比较将产生“相等”的结果可能double 到那个值。如果人们认识到浮点类型实际上并不表示单个精确值,而是表示一个值范围,那么这种行为是有意义的。

    【讨论】:

      【解决方案5】:
      double val1 = 0;
      double val2 = 0.0;
      if((val1 - Double.Epsilon) < 0)
      {
          // Put your code here
      }
      
            OR
      
      if((val2 - Double.Epsilon) < 0)
      {
          // Put your code here
      }
      

      其中 Double.Epsilon 是 Double 的最低可能值。

      【讨论】:

      • 读者,请参阅主要问题下乔伊的评论。
      【解决方案6】:

      来自https://docs.microsoft.com/en-us/dotnet/api/system.double.equals?view=netframework-4.8#System_Double_Equals_System_Double_

      因为 Epsilon 定义了正值的最小表达式 其范围接近于零,两个相似的差值 值必须大于 Epsilon。通常是多次 大于厄普西隆。因此,我们建议您不要 在比较 Double 值是否相等时使用 Epsilon。

      【讨论】:

        【解决方案7】:

        如果您没有使用双精度进行任何计算,您可以使用==。这是因为整数可以精确地用双精度表示(仅在 -2^53 和 2^53 之间)。

        int iValue = 0;
        double dValue = 0.0;
        
        bool isEqual = iValue == dValue;
        

        这返回真。

        Equals 不起作用的原因是== 运算符会在比较之前自动将整数转换为双精度数,而Equals 不会因此失败。

        这个答案有更多信息: https://stackoverflow.com/a/52525223/15714398

        如果您使用双精度数进行了计算,则所有赌注都已取消,您必须对计算中的有效数字数进行一些分析。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-08-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多