Udostępnij za pośrednictwem


Metody System.Double.CompareTo

Ten artykuł zawiera dodatkowe uwagi dotyczące dokumentacji referencyjnej dla tego interfejsu API.

Metoda CompareTo(Double)

Wartości muszą być identyczne, aby można je było uznać za równe. Szczególnie w przypadku, gdy wartości zmiennoprzecinkowe zależą od wielu operacji matematycznych, często zdarza się, że tracą precyzję i wartości są prawie identyczne, z wyjątkiem ich najmniej znaczących cyfr. Z tego powodu wartość zwracana metody CompareTo czasami może wydawać się zaskakująca. Na przykład mnożenie określonej wartości, po której następuje dzielenie przez tę samą wartość, powinno spowodować wygenerowanie oryginalnej wartości. Jednak w poniższym przykładzie obliczona wartość jest większa niż oryginalna wartość. Wyświetlanie wszystkich znaczących cyfr dwóch wartości przy użyciu ciągu "R" standardowego ciągu formatu liczbowego wskazuje, że obliczona wartość różni się od oryginalnej wartości w najmniej znaczących cyfrach. Aby uzyskać informacje na temat obsługi takich porównań, zobacz sekcję Uwagi metody Equals(Double).

using System;

public class Example
{
    public static void Main()
    {
        double value1 = 6.185;
        double value2 = value1 * .1 / .1;
        Console.WriteLine($"Comparing {value1} and {value2}: {value1.CompareTo(value2)}{Environment.NewLine}");
        Console.WriteLine($"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
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

Ta metoda implementuje interfejs System.IComparable<T> i działa nieco lepiej niż metoda Double.CompareTo, ponieważ nie musi konwertować parametru value na obiekt.

Należy pamiętać, że chociaż obiekt, którego wartość jest NaN nie jest traktowany jako równy innemu obiektowi, którego wartość jest NaN (nawet sama), interfejs IComparable<T> wymaga, aby A.CompareTo(A) zwrócić zero.

Metoda CompareTo(Object)

Parametr value musi być null lub instancją Double; w przeciwnym razie zgłaszany jest wyjątek. Każde wystąpienie Double, niezależnie od jego wartości, jest uznawane za większe niż null.

Wartości muszą być identyczne, aby można je było uznać za równe. Szczególnie w przypadku, gdy wartości zmiennoprzecinkowe zależą od wielu operacji matematycznych, często zdarza się, że tracą precyzję i wartości są prawie identyczne, z wyjątkiem ich najmniej znaczących cyfr. Z tego powodu wartość zwracana metody CompareTo czasami może wydawać się zaskakująca. Na przykład mnożenie określonej wartości, po której następuje dzielenie przez tę samą wartość, powinno spowodować wygenerowanie oryginalnej wartości. Jednak w poniższym przykładzie obliczona wartość jest większa niż oryginalna wartość. Wyświetlanie wszystkich znaczących cyfr dwóch wartości przy użyciu ciągu "R" standardowego ciągu formatu liczbowego wskazuje, że obliczona wartość różni się od oryginalnej wartości w najmniej znaczących cyfrach. Aby uzyskać informacje na temat obsługi takich porównań, zobacz sekcję Uwagi metody Equals(Double).

using System;

public class Example3
{
    public static void Main()
    {
        double value1 = 6.185;
        object value2 = value1 * .1 / .1;
        Console.WriteLine($"Comparing {value1} and {value2}: {value1.CompareTo(value2)}{Environment.NewLine}");
        Console.WriteLine($"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
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

Ta metoda jest implementowana w celu obsługi interfejsu IComparable. Należy pamiętać, że chociaż NaN nie jest traktowana jako równa innej NaN (nawet samej sobie), interfejs IComparable wymaga, aby A.CompareTo(A) zwrócić zero.

Konwersje rozszerzające

W zależności od języka programowania można kodować metodę CompareTo, w której typ parametru ma mniej bitów (jest węższy) niż typ wystąpienia. Jest to możliwe, ponieważ niektóre języki programowania wykonują niejawną konwersję rozszerzającą, która reprezentuje parametr jako typ z tyloma bitami co wystąpienie.

Załóżmy na przykład, że typ wystąpienia jest Double, a typ parametru to Int32. Kompilator języka Microsoft C# generuje instrukcje reprezentujące wartość parametru jako obiekt Double, a następnie generuje metodę Double.CompareTo(Double), która porównuje wartości wystąpienia i poszerzone reprezentacje parametru.

Zapoznaj się z dokumentacją języka programowania, aby ustalić, czy kompilator wykonuje niejawne konwersje rozszerzające typy liczbowe. Aby uzyskać więcej informacji, zapoznaj się z tematem Tabele konwersji typów.

Precyzja w porównaniach

Precyzja liczb zmiennoprzecinkowych poza udokumentowaną precyzją jest specyficzna dla implementacji i wersji platformy .NET. W związku z tym porównanie dwóch konkretnych liczb może ulec zmianie między wersjami platformy .NET, ponieważ precyzja wewnętrznej reprezentacji liczb może ulec zmianie.