Методы System.Double.CompareTo

В этой статье приводятся дополнительные замечания к справочной документации по этому API.

CompareTo(Double)Метод

Значения должны быть идентичными, которые считаются равными. Особенно, если значения с плавающей запятой зависят от нескольких математических операций, они часто теряют точность и для их значений почти идентичны, за исключением их наименее значимых цифр. Из-за этого возвращаемое значение CompareTo метода иногда может показаться удивительным. Например, умножение на определенное значение, за которым следует деление по тому же значению, должно производить исходное значение. Однако в следующем примере вычисляемое значение оказывается больше исходного значения. Отображение всех значимых цифр двух значений с помощью строки стандартного числового формата R указывает на то, что вычисляемое значение отличается от исходного значения в его наименее значимых цифрах. Сведения об обработке таких сравнений Equals(Double) см. в разделе "Примечания" метода.

using System;

public class Example
{
    public static void Main()
    {
        double value1 = 6.185;
        double value2 = value1 * .1 / .1;
        Console.WriteLine("Comparing {0} and {1}: {2}\n",
                          value1, value2, value1.CompareTo(value2));
        Console.WriteLine("Comparing {0:R} and {1:R}: {2}",
                          value1, value2, value1.CompareTo(value2));
    }
}
// The example displays the following output:
//       Comparing 6.185 and 6.185: -1
//
//       Comparing 6.185 and 6.1850000000000005: -1
let value1 = 6.185
let value2 = value1 * 0.1 / 0.1
printfn $"Comparing {value1} and {value2}: {value1.CompareTo value2}\n"
printfn $"Comparing {value1:R} and {value2:R}: {value1.CompareTo value2}"
// The example displays the following output:
//       Comparing 6.185 and 6.185: -1
//
//       Comparing 6.185 and 6.1850000000000005: -1
Module Example
   Public Sub Main()
       Dim value1 As Double = 6.185
       Dim value2 As Double = value1 * .1 / .1
       Console.WriteLine("Comparing {0} and {1}: {2}",
                         value1, value2, value1.CompareTo(value2))
       Console.WriteLine()
       Console.WriteLine("Comparing {0:R} and {1:R}: {2}",
                         value1, value2, value1.CompareTo(value2))
   End Sub
End Module
' The example displays the following output:
'       Comparing 6.185 and 6.185: -1
'       
'       Comparing 6.185 and 6.1850000000000005: -1

Этот метод реализует System.IComparable<T> интерфейс и выполняет немного лучше, Double.CompareTo чем метод, так как он не должен преобразовать value параметр в объект.

Обратите внимание, что, хотя объект, значение NaN которого не считается равным другому объекту, значение NaN которого (даже само по себе), IComparable<T> интерфейс должен A.CompareTo(A) возвращать ноль.

CompareTo(Object)Метод

Параметр value должен быть null или экземпляром Double; в противном случае создается исключение. Любой Doubleэкземпляр , независимо от его значения, считается больше null.

Значения должны быть идентичными, которые считаются равными. Особенно, если значения с плавающей запятой зависят от нескольких математических операций, они часто теряют точность и для их значений почти идентичны, за исключением их наименее значимых цифр. Из-за этого возвращаемое значение CompareTo метода иногда может показаться удивительным. Например, умножение на определенное значение, за которым следует деление по тому же значению, должно производить исходное значение. Однако в следующем примере вычисляемое значение оказывается больше исходного значения. Отображение всех значимых цифр двух значений с помощью строки стандартного числового формата R указывает на то, что вычисляемое значение отличается от исходного значения в его наименее значимых цифрах. Сведения об обработке таких сравнений Equals(Double) см. в разделе "Примечания" метода.

using System;

public class Example3
{
    public static void Main()
    {
        double value1 = 6.185;
        object value2 = value1 * .1 / .1;
        Console.WriteLine("Comparing {0} and {1}: {2}\n",
                          value1, value2, value1.CompareTo(value2));
        Console.WriteLine("Comparing {0:R} and {1:R}: {2}",
                          value1, value2, value1.CompareTo(value2));
    }
}
// The example displays the following output:
//       Comparing 6.185 and 6.185: -1
//
//       Comparing 6.185 and 6.1850000000000005: -1
let value1 = 6.185
let value2 = value1 * 0.1 / 0.1 |> box
printfn $"Comparing {value1} and {value2}: {value1.CompareTo value2}\n"
printfn $"Comparing {value1:R} and {value2:R}: {value1.CompareTo value2}"
// The example displays the following output:
//       Comparing 6.185 and 6.185: -1
//
//       Comparing 6.185 and 6.1850000000000005: -1
Module Example2
   Public Sub Main()
       Dim value1 As Double = 6.185
       Dim value2 As Object = value1 * .1 / .1
       Console.WriteLine("Comparing {0} and {1}: {2}",
                         value1, value2, value1.CompareTo(value2))
       Console.WriteLine()
       Console.WriteLine("Comparing {0:R} and {1:R}: {2}",
                         value1, value2, value1.CompareTo(value2))
   End Sub
End Module
' The example displays the following output:
'       Comparing 6.185 and 6.185: -1
'       
'       Comparing 6.185 and 6.1850000000000005: -1

Этот метод реализуется для поддержки IComparable интерфейса. Обратите внимание, что, хотя не NaN считается равным другому NaN (даже самому себе), IComparable интерфейсу требуется, чтобы A.CompareTo(A) возвращать ноль.

Расширение преобразований

В зависимости от языка программирования можно закодировать CompareTo метод, в котором тип параметра имеет меньше битов (является более узким), чем тип экземпляра. Это возможно, так как некоторые языки программирования выполняют неявное расширение преобразования, представляющее параметр как тип с большим количеством битов, как экземпляр.

Например, предположим, что тип экземпляра имеет тип Double , а тип параметра — Int32. Компилятор Microsoft C# создает инструкции для представления значения параметра в качестве Double объекта, а затем создает Double.CompareTo(Double) метод, который сравнивает значения экземпляра и расширенный представление параметра.

Ознакомьтесь с документацией по языку программирования, чтобы определить, выполняет ли компилятор неявное расширение преобразований числовых типов. Дополнительные сведения см. в разделе "Таблицы преобразования типов".

Точность сравнения

Точность чисел с плавающей запятой за пределами документированной точности зависит от реализации и версии .NET. Следовательно, сравнение двух конкретных чисел может измениться между версиями .NET, так как точность внутреннего представления чисел может измениться.