Методы 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, так как точность внутреннего представления чисел может измениться.