【问题标题】:C# Compare two double with .Equals()C# 用 .Equals() 比较两个双精度
【发布时间】:2023-03-11 22:04:01
【问题描述】:

我使用 ReShaper,当我用 == 比较两个双精度值时,它建议我应该使用 Math.具有公差的 ABS 方法。见:https://www.jetbrains.com/help/resharper/2016.2/CompareOfFloatsByEqualityOperator.html

这个例子

double d = 0.0;
double d2 = 0.0;
if (d == d2)
{
    /* some code */
}

然后转换为

double d = 0.0;
double d2 = 0.0;
if (Math.Abs(d - d2) < TOLERANCE)
{
    /* some code */
}

但我认为,对于开发人员来说,考虑正确的容差确实很复杂。所以我认为这可能在 Double.Equals() 方法中实现。

但是这个方法是这样实现的

public override bool Equals(Object obj) {
    if (!(obj is Double)) { 
        return false;
    } 
    double temp = ((Double)obj).m_value; 
    // This code below is written this way for performance reasons i.e the != and == check is intentional.
    if (temp == m_value) { 
        return true;
    }
    return IsNaN(temp) && IsNaN(m_value);
}

public bool Equals(Double obj)
{ 
    if (obj == m_value) {
        return true; 
    } 
    return IsNaN(obj) && IsNaN(m_value);
}

这是为什么呢?比较双精度值的正确方法是什么?

【问题讨论】:

  • 为什么不使用十进制? if(double1
  • 如果您发现 开发人员 难以获得容忍度,那么 .NET-framework 应该如何决定,因为它的容忍度要低得多知道你认为什么是平等的。
  • @HimBromBeere 我认为他们可能会使用 double.Epsilon 作为默认容差,或者这是一个坏主意?
  • 它在您提供的文档中说,在大多数情况下,Epsilon 被认为太低而不能成为默认容差。
  • 什么是比较双精度值的正确方法 - 没有办法 - 你不能检查 doublereal 相等性。在需要检查相等性的情况下不要使用double,而是使用decimal

标签: c# compare double


【解决方案1】:

你可以创建一个扩展方法

public static class DoubleExtension 
{
    public static bool AlmostEqualTo(this double value1, double value2)
    {
        return Math.Abs(value1 - value2) < 0.0000001; 
    }
}

并像这样使用它

doubleValue.AlmostEqualTo(doubleValue2)

【讨论】:

  • 这种方法对于每个人都使用这种扩展方法的大项目来说是非常危险的。想象一下value1.EqualDouble(value2) == true 的情况,那么如果value1.EqualDouble(value3) == true 也很容易假设value2.EqualDouble(value3) == true - 但在某些情况下并非如此。因此,建议至少将名称更改为更具信息性的名称 CloseTo 来回示例
  • 谢谢! C# 具有的 Double.Equals 方法没有实现 epsilon,因此测试 0.5 == 0.5 之类的东西给了我一个错误的标志。顺便说一句,我将您的方法修改为普通方法而不是扩展,例如: public static boolAlmostEqualTo(double value1, double value2) { return Math.Abs​​(value1 - value2)
【解决方案2】:

我最终使用了

double piConstant = 3.142;
double piFractional = 7/22;
if(piConstatnt.String("{0:0.00}")==piFractional.String("{0:0.00}")
{
    // some code
}

这让我可以通过设置所需的字符串格式来控制精度。 https://www.csharp-examples.net/string-format-double/

如果您想了解有关 Microsoft 的 Equals 方法的更多信息。 https://docs.microsoft.com/en-us/dotnet/api/system.double.equals?view=net-5.0

【讨论】:

    【解决方案3】:

    https://docs.microsoft.com/en-us/dotnet/api/system.numerics.complex.equals?view=net-6.0

    如果obj参数不是Complex对象,而是数据类型 为其定义了隐式转换的 Equals(Object) 方法 将 obj 转换为实部等于值的 Complex 对象 obj 的虚部在执行之前等于 0 比较。以下示例通过发现 复数和双精度浮点值是 相等。

    double n1 = 16.33;
    System.Numerics.Complex c1 =
    new System.Numerics.Complex(16.33, 0);
    Console.WriteLine(c1.Equals(n1));               // Returns true.
    

    【讨论】:

      猜你喜欢
      • 2018-06-05
      • 1970-01-01
      • 2015-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-22
      • 1970-01-01
      相关资源
      最近更新 更多