В информатике , А сравнение трехходового принимает два значения А и В , принадлежащих к типу с общим порядка и определяет , является ли A B в одной операции, в соответствии с математическим ,>законом трихотомия .
Вычисление на уровне машины
Многие процессоры имеют наборы инструкций, которые поддерживают такую операцию над примитивными типами. Некоторые машины имеют целые числа со знаком, основанные на знаке и величине или одном дополнительном представлении (см. Представление чисел со знаком ), оба из которых позволяют дифференцировать положительный и отрицательный ноль . Это не нарушает трихотомию до тех пор, пока принят согласованный общий порядок: допустимо либо -0 = +0, либо -0 <+0. Однако общие типы с плавающей запятой имеют исключение из трихотомии: существует специальное значение «NaN» ( не число ), такое, что x
Языки высокого уровня
Возможности
В C функции strcmp
и memcmp
выполняют трехстороннее сравнение между строками и буферами памяти соответственно. Они возвращают отрицательное число, когда первый аргумент лексикографически меньше второго, ноль, когда аргументы равны, и положительное число в противном случае. Это соглашение о возврате «знака различия» распространяется на произвольные функции сравнения стандартной функцией сортировки qsort
, которая принимает функцию сравнения в качестве аргумента и требует, чтобы она выполняла ее.
В C ++ , то ++ 20 C редакция добавляет «космический корабль оператор» <=>
, который так же возвращает знак разности , а также может возвращать различные типы (конвертируемые в целые числа) в зависимости от строгости сравнения. [1]
В Perl (только для числовых сравнений cmp
оператор используется для лексических сравнений строк), PHP (начиная с версии 7), Ruby и Apache Groovy «оператор космического корабля» <=>
возвращает значения -1, 0 или 1 в зависимости от того, A B соответственно. ,>Функции Python 2.x cmp
(удален в 3.x), OCaml compare
и Kotlin compareTo
вычисляют одно и то же. В стандартной библиотеке Haskell функция трехстороннего сравнения compare
определена для всех типов в Ord
классе ; он возвращает тип Ordering
, значения которого: LT
(меньше), EQ
(равно) и GT
(больше): [2]
данные Ordering = LT | EQ | GT
Многие объектно-ориентированные языки имеют метод трехстороннего сравнения , который выполняет трехстороннее сравнение между объектом и другим заданным объектом. Например, в Java любой класс, реализующий Comparable
интерфейс, имеет compareTo
метод, который либо возвращает отрицательное целое число, ноль или положительное целое число, либо выдает NullPointerException
(если один или оба объекта null
). Точно так же в .NET Framework любой класс, реализующий IComparable
интерфейс, имеет такой CompareTo
метод.
Начиная с версии Java 1.5, то же самое можно вычислить с помощью Math.signum
статического метода, если разница может быть известна без вычислительных проблем, таких как арифметическое переполнение, упомянутое ниже. Многие компьютерные языки допускают определение функций, поэтому сравнение (A, B) может быть разработано соответствующим образом, но вопрос в том, может ли его внутреннее определение использовать какой-то трехсторонний синтаксис, или же необходимо использовать повторные тесты.
При реализации трехстороннего сравнения, когда оператор или метод трехстороннего сравнения еще не доступны, обычно объединяют два сравнения, например A = B и A B. , компилятор может сделать вывод, что эти два выражения могут быть заменены только одним сравнением с последующими несколькими проверками результата, но упоминания об этой оптимизации нельзя найти в текстах по этой теме.
В некоторых случаях трехстороннее сравнение можно смоделировать, вычитая A и B и проверяя знак результата, используя специальные инструкции для проверки знака числа. Однако для этого требуется, чтобы типы A и B имели четко выраженную разницу. Целые числа фиксированной ширины со знаком могут переполняться при вычитании, числа с плавающей запятой имеют значение NaN с неопределенным знаком, а символьные строки не имеют функции разницы, соответствующей их общему порядку. На машинном уровне переполнение обычно отслеживается и может использоваться для определения порядка после вычитания, но эта информация обычно недоступна для языков более высокого уровня.
В одном случае трехстороннего условного выражения, предоставляемого языком программирования, теперь устаревший трехсторонний арифметический оператор IF в Фортране учитывает знак арифметического выражения и предлагает три метки для перехода в соответствии со знаком результата:
ЕСЛИ ( выражение ) отрицательный , ноль , положительный
Общая библиотечная функция strcmp в C и родственных языках - это трехстороннее лексикографическое сравнение строк; однако в этих языках отсутствует общее трехстороннее сравнение других типов данных.
Оператор космического корабля
Оператор трехстороннего сравнения чисел обозначается как <=>
в Perl , Ruby , Apache Groovy , PHP , Eclipse Ceylon и C ++ и называется оператором космического корабля . [3]
Название происходит из-за того, что оно напоминает Рэндалу Л. Шварцу космический корабль из игры HP BASIC Star Trek . [4] Другой программист предположил, что он был назван так, потому что он был похож на СИД-истребитель Дарта Вейдера из саги « Звездные войны ». [5]
Пример на PHP:
эхо 1 <=> 1 ; // 0 эхо 1 <=> 2 ; // -1 эхо 2 <=> 1 ; // 1
Составные типы данных
Трехсторонние сравнения имеют свойство легко составлять и строить лексикографические сравнения непримитивных типов данных, в отличие от двусторонних сравнений.
Вот пример композиции на Perl.
sub compare ($$) { мой ( $ a , $ b ) = @_ ; return $ a -> { unit } cmp $ b -> { unit } || $ a -> { rank } <=> $ b -> { rank } || $ a -> { имя } cmp $ b -> { имя }; }
Обратите внимание, что cmp
в Perl это для строк, так <=>
как для чисел. Двусторонние эквиваленты, как правило, менее компактны, но не обязательно менее разборчивы. Выше , имеет преимущество оценки короткого замыкания на ||
оператора, а также тот факт , что 0 считается ложным в Perl. В результате, если первое сравнение равно (таким образом, оценивается как 0), оно «провалится» до второго сравнения и так далее, пока не найдет одно, отличное от нуля, или пока не достигнет конца.
В некоторых языках, включая Python , Ruby , Haskell и т. Д., Сравнение списков выполняется лексикографически, что означает, что можно построить цепочку сравнений, как в приведенном выше примере, помещая значения в списки в желаемом порядке; например, в Ruby:
[ а . блок , а . ранг , а . имя ] <=> [ б . блок , б . ранг , б . имя ]
Смотрите также
- strcmp
Рекомендации
- ^ Херб Саттер предложил добавить к стандарту C ++ оператор трехстороннего сравнения с
<=>
синтаксисом в статье, озаглавленной «Согласованное сравнение». См. «Последовательное сравнение». Он был успешно объединен с черновиком C ++ 20 в ноябре 2017 года. - ^ Data.Ord
- ^ «Математика :: Комплекс» . Документация по программированию на Perl . Проверено 26 сентября 2014 года .
- ^ "История космического корабля (Re: [dart-misc] Заметки о встрече DEP)" .
- ^ «Оператор супер космического корабля» . 2000-12-08 . Проверено 6 августа 2014 .