Методы System.Single.CompareTo

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

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

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

CompareTo(System.Object)

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

using System;

public class Example
{
   public static void Main()
   {
       float value1 = 16.5457f;
       float operand = 3.8899982f;
       object value2 = value1 * operand / operand;
       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 16.5457 and 16.5457: -1
//       
//       Comparing 16.5457 and 16.545702: -1
let value1 = 16.5457f
let operand = 3.8899982f
let value2 = box (value1 * operand / operand)
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 16.5457 and 16.5457: -1
//       
//       Comparing 16.5457 and 16.545702: -1
Module Example2
    Public Sub Main()
        Dim value1 As Single = 16.5457
        Dim value2 As Object = value1 * CSng(3.8899982) / CSng(3.8899982)
        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 16.5457 and 16.5457: -1
'       
'       Comparing 16.5457 and 16.545702: -1

Этот метод реализуется для поддержки IComparable интерфейса.

CompareTo(System.Single)

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

using System;

public class Example2
{
   public static void Main()
   {
       float value1 = 16.5457f;
       float operand = 3.8899982f;
       float value2 = value1 * operand / operand;
       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 16.5457 and 16.5457: -1
//       
//       Comparing 16.5457 and 16.545702: -1
let value1 = 16.5457f
let operand = 3.8899982f
let value2 = value1 * operand / operand
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 16.5457 and 16.5457: -1
//       
//       Comparing 16.5457 and 16.545702: -1
Module Example
   Public Sub Main()
       Dim value1 As Single = 16.5457
       Dim value2 As Single = value1 * CSng(3.8899982) / CSng(3.8899982)
       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 16.5457 and 16.5457: -1
'       
'       Comparing 16.5457 and 16.545702: -1

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

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

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

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

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

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