Tw-city.info

IT Новости
10 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Знак не равно в программировании

Логические выражения и операторы

Логические выражения и логический тип данных

Часто в реальной жизни мы соглашаемся с каким-либо утверждением или отрицаем его. Например, если вам скажут, что сумма чисел 3 и 5 больше 7, вы согласитесь, скажете: «Да, это правда». Если же кто-то будет утверждать, что сумма трех и пяти меньше семи, то вы расцените такое утверждение как ложное.

Подобные фразы предполагают только два возможных ответа – либо «да», когда выражение оценивается как правда, истина, либо «нет», когда утверждение оценивается как ошибочное, ложное. В программировании и математике если результатом вычисления выражения может быть лишь истина или ложь, то такое выражение называется логическим.

Например, выражение 4 > 5 является логическим, так как его результатом является либо правда, либо ложь. Выражение 4 + 5 не является логическим, так как результатом его выполнения является число.

На позапрошлом уроке мы познакомились с тремя типами данных – целыми и вещественными числами, а также строками. Сегодня введем четвертый – логический тип данных (тип bool). Его также называют булевым. У этого типа всего два возможных значения: True (правда) и False (ложь).

Здесь переменной a было присвоено значение True, после чего с помощью встроенной в Python функции type() проверен ее тип. Интерпретатор сообщил, что это переменная класса bool. Понятия «класс» и «тип данных» в данном случае одно и то же. Переменная b также связана с булевым значением.

В программировании False обычно приравнивают к нулю, а True – к единице. Чтобы в этом убедиться, можно преобразовать булево значение к целочисленному типу:

Возможно и обратное. Можно преобразовать какое-либо значение к булевому типу:

И здесь работает правило: всё, что не 0 и не пустота, является правдой.

Логические операторы

Говоря на естественном языке (например, русском) мы обозначаем сравнения словами «равно», «больше», «меньше». В языках программирования используются специальные знаки, подобные тем, которые используются в математике: > (больше), = (больше или равно), c = a == b состоит из двух подвыражений. Сначала происходит сравнение (==) переменных a и b . После этого результат логической операции присваивается переменной c. Выражение a , b , c просто выводит значения переменных на экран.

Сложные логические выражения

Логические выражения типа kByte >= 1023 являются простыми, так как в них выполняется только одна логическая операция. Однако, на практике нередко возникает необходимость в более сложных выражениях. Может понадобиться получить ответа «Да» или «Нет» в зависимости от результата выполнения двух простых выражений. Например, «на улице идет снег или дождь», «переменная news больше 12 и меньше 20».

В таких случаях используются специальные операторы, объединяющие два и более простых логических выражения. Широко используются два оператора – так называемые логические И (and) и ИЛИ (or).

Чтобы получить True при использовании оператора and, необходимо, чтобы результаты обоих простых выражений, которые связывает данный оператор, были истинными. Если хотя бы в одном случае результатом будет False, то и все сложное выражение будет ложным.

Чтобы получить True при использовании оператора or, необходимо, чтобы результат хотя бы одного простого выражения, входящего в состав сложного, был истинным. В случае оператора or сложное выражение становится ложным лишь тогда, когда ложны оба составляющие его простые выражения.

Допустим, переменной x было присвоено значение 8 ( x = 8 ), переменной y присвоили 13 ( y = 13 ). Логическое выражение y 8 будет выполняться следующим образом. Сначала выполнится выражение y . Его результатом будет True. Затем выполнится выражение x > 8 . Его результатом будет False. Далее выражение сведется к True and False , что вернет False.

Если бы мы записали выражение так: x > 8 and y , то оно также вернуло бы False. Однако сравнение y не выполнялось бы интерпретатором, так как его незачем выполнять. Ведь первое простое логическое выражение ( x > 8 ) уже вернуло ложь, которая, в случае оператора and, превращает все выражение в ложь.

В случае с оператором or второе простое выражение проверяется, если первое вернуло ложь, и не проверяется, если уже первое вернуло истину. Так как для истинности всего выражения достаточно единственного True, неважно по какую сторону от or оно стоит.

В языке Python есть еще унарный логический оператор not, т. е. отрицание. Он превращает правду в ложь, а ложь в правду. Унарный он потому, что применяется к одному выражению, стоящему после него, а не справа и слева от него как в случае бинарных and и or.

Здесь у возвращает True. Отрицая это, мы получаем False.

Число 5 трактуется как истина, отрицание истины дает ложь. Ноль приравнивается к False. Отрицание False дает True.

Практическая работа

Присвойте двум переменным любые числовые значения.

Используя переменные из п. 1, с помощью оператора and составьте два сложных логических выражения, одно из которых дает истину, другое – ложь.

Аналогично выполните п. 2, но уже с оператором or.

Попробуйте использовать в логических выражениях переменные строкового типа. Объясните результат.

Напишите программу, которая запрашивала бы у пользователя два числа и выводила бы True или False в зависимости от того, больше первое число второго или нет.

Примеры решения и дополнительные уроки в android-приложении и pdf-версии курса.

Операторы отношения и логические операторы

C# — Руководство по C# — Операторы отношения и логические операторы

В обозначениях оператор отношения и логический оператор термин отношения означает взаимосвязь, которая может существовать между двумя значениями, а термин логический — взаимосвязь между логическими значениями «истина» и «ложь». И поскольку операторы отношения дают истинные или ложные результаты, то они нередко применяются вместе с логическими операторами. Именно по этой причине они и рассматриваются совместно.

Ниже перечислены операторы отношения:

Результатом выполнения оператора отношения или логического оператора является логическое значение типа bool.

В целом, объекты можно сравнивать на равенство или неравенство, используя операторы отношения == и !=. А операторы сравнения , = могут применяться только к тем типам данных, которые поддерживают отношение порядка. Следовательно, операторы отношения можно применять ко всем числовым типам данных. Но значения типа bool могут сравниваться только на равенство или неравенство, поскольку истинные (true) и ложные (false) значения не упорядочиваются. Например, сравнение true > false в C# не имеет смысла.

Рассмотрим пример программы, демонстрирующий применение операторов отношения и логических операторов:

Логические операторы в C# выполняют наиболее распространенные логические операции. Тем не менее существует ряд операций, выполняемых по правилам формальной логики. Эти логические операции могут быть построены с помощью логических операторов, поддерживаемых в C#. Следовательно, в C# предусмотрен такой набор логических операторов, которого достаточно для построения практически любой логической операции, в том числе импликации. Импликация — это двоичная операция, результатом которой является ложное значение только в том случае, если левый ее операнд имеет истинное значение, а правый — ложное. (Операция импликации отражает следующий принцип: истина не может подразумевать ложь .)

Операция импликации может быть построена на основе комбинации логических операторов ! и |:

Укороченные логические операторы

В C# предусмотрены также специальные, укороченные, варианты логических операторов И и ИЛИ, предназначенные для получения более эффективного кода. Поясним это на следующих примерах логических операций. Если первый операнд логической операции И имеет ложное значение (false), то ее результат будет иметь ложное значение независимо от значения второго операнда. Если же первый операнд логической операции ИЛИ имеет истинное значение (true), то ее результат будет иметь истинное значение независимо от значения второго операнда. Благодаря тому что значение второго операнда в этих операциях вычислять не нужно, экономится время и повышается эффективность кода.

Укороченная логическая операция И выполняется с помощью оператора &&, а укороченная логическая операция ИЛИ — с помощью оператора ||. Этим укороченным логическим операторам соответствуют обычные логические операторы & и |. Единственное отличие укороченного логического оператора от обычного заключается в том, что второй его операнд вычисляется только по мере необходимости.

Читать еще:  Язык программирования шарп

Укороченные логические операторы иногда оказываются более эффективными, чем их обычные аналоги. Так зачем же нужны обычные логические операторы И и ИЛИ? Дело в том, что в некоторых случаях требуется вычислять оба операнда логической операции И либо ИЛИ из-за возникающих побочных эффектов. Пример:

Стоит отметить, что при возникновении исключительной ситуации во время отладки кода, Visual Studio 2010 выводит сообщение следующего характера:

Знак не равно в программировании

Операторы == (равенство) и != (неравенство) проверяют равенство или неравенство своих операндов. The == (equality) and != (inequality) operators check if their operands are equal or not.

Оператор равенства == Equality operator ==

Оператор равенства == возвращает значение true , если его операнды равны. В противном случае возвращается значение false . The equality operator == returns true if its operands are equal, false otherwise.

Равенство типов значений Value types equality

Операнды встроенных типов значений равны, если равны их значения. Operands of the built-in value types are equal if their values are equal:

У операторов == , , > , и >= , если какой-то из операндов не является числом (Double.NaN или Single.NaN), результатом операции является false . For the == , , > , , and >= operators, if any of the operands is not a number (Double.NaN or Single.NaN), the result of operation is false . Это означает, что значение NaN не больше, не меньше и не равно любому другому значению double (или float ), включая NaN . That means that the NaN value is neither greater than, less than, nor equal to any other double (or float ) value, including NaN . Дополнительные сведения и примеры см. в справочных статьях по Double.NaN или Single.NaN. For more information and examples, see the Double.NaN or Single.NaN reference article.

Два операнда одного типа enum равны, если равны соответствующие значения базового целочисленного типа. Two operands of the same enum type are equal if the corresponding values of the underlying integral type are equal.

По умолчанию пользовательские типы struct не поддерживают оператор == . User-defined struct types don’t support the == operator by default. Чтобы поддерживать оператор == , пользовательская структура должна перегружать его. To support the == operator, a user-defined struct must overload it.

Начиная с версии C# 7.3 операторы == и != поддерживаются кортежами C#. Beginning with C# 7.3, the == and != operators are supported by C# tuples. Дополнительные сведения см. в разделе Равенство и кортежи статьи Типы кортежей в C#. For more information, see the Equality and tuples section of the C# tuple types article.

Равенство ссылочных типов Reference types equality

По умолчанию два операнда ссылочного типа являются равными, если они ссылаются на один и тот же объект: By default, two reference-type operands are equal if they refer to the same object:

Как показано в примере, определяемые пользователем ссылочные типы поддерживают оператор == по умолчанию. As the example shows, user-defined reference types support the == operator by default. Однако ссылочный тип может перегружать оператор == . However, a reference type can overload the == operator. Если ссылочный тип перегружает оператор == , воспользуйтесь методом Object.ReferenceEquals, чтобы проверить, что две ссылки этого типа указывают на один и тот же объект. If a reference type overloads the == operator, use the Object.ReferenceEquals method to check if two references of that type refer to the same object.

Равенство строк String equality

Два операнда string равны, если они оба имеют значение null или оба экземпляра строки имеют одинаковую длину и идентичные символы в каждой позиции символа. Two string operands are equal when both of them are null or both string instances are of the same length and have identical characters in each character position:

Это порядковое сравнение, учитывающее регистр. That is a case-sensitive ordinal comparison. Дополнительные сведения о том, как сравнивать строки, см. в статье Сравнение строк в C#. For more information about string comparison, see How to compare strings in C#.

Равенство делегатов Delegate equality

Два операнда delegate одного типа среды выполнения равны, если оба из них имеют значение null или их списки вызовов имеют одинаковую длину и содержат одинаковые записи в каждой позиции: Two delegate operands of the same runtime type are equal when both of them are null or their invocation lists are of the same length and have equal entries in each position:

Подробные сведения см. в разделе Delegate equality operators (Операторы равенства делегатов) в спецификации языка C#. For more information, see the Delegate equality operators section of the C# language specification.

Делегаты, созданные в результате оценки семантически идентичных лямбда-выражений не будут равны, как показано в примере ниже: Delegates that are produced from evaluation of semantically identical lambda expressions are not equal, as the following example shows:

Оператор неравенства != Inequality operator !=

Оператор неравенства != возвращает значение true , если его операнды не равны. В противном случае возвращается значение false . The inequality operator != returns true if its operands are not equal, false otherwise. Для операндов встроенных типов выражение x != y дает тот же результат, что и выражение !(x == y) . For the operands of the built-in types, the expression x != y produces the same result as the expression !(x == y) . Дополнительные сведения о равенстве типов см. в разделе Оператор равенства. For more information about type equality, see the Equality operator section.

В следующем примере иллюстрируется использование оператора != . The following example demonstrates the usage of the != operator:

Возможность перегрузки оператора Operator overloadability

Определяемый пользователем тип может перегружать операторы == и != . A user-defined type can overload the == and != operators. Если тип перегружает один из двух операторов, он должен также перегружать и другой. If a type overloads one of the two operators, it must also overload another one.

В математике повсеместно используются символы для упрощения и сокращения текста. Ниже приведён список наиболее часто встречающихся математических обозначений, соответствующие команды в TeX, объяснения и примеры использования. Список и смысл обозначений соответствует международным стандартам ISO 31-11 и ISO 80000-2.

Кроме указанных символов, иногда используются их зеркальные отражения, например, A ⊂ B обозначает то же, что и B ⊃ A .

Знаки операций, или математические символы — знаки, которые символизируют определённые математические действия со своими аргументами.

Многие операторы сравнения известны нам из математики:

  • Больше/меньше: a > b , a .
  • Больше/меньше или равно: a >= b , a .
  • Равно: a == b . Обратите внимание, для сравнения используется двойной знак равенства = . Один знак равенства a = b означал бы присваивание.
  • Не равно. В математике обозначается символом ≠ . В JavaScript записывается как знак равенства с предшествующим ему восклицательным знаком: a != b .

Результат сравнения имеет логический тип

Операторы сравнения, как и другие операторы, возвращают значение. Это значение имеет логический тип.

  • true – означает «да», «верно», «истина».
  • false – означает «нет», «неверно», «ложь».

Результат сравнения можно присвоить переменной, как и любое значение:

Сравнение строк

Чтобы определить, что одна строка больше другой, JavaScript использует «алфавитный» или «лексикографический» порядок.

Другими словами, строки сравниваются посимвольно.

Алгоритм сравнения двух строк довольно прост:

  1. Сначала сравниваются первые символы строк.
  2. Если первый символ первой строки больше (меньше), чем первый символ второй, то первая строка больше (меньше) второй.
  3. Если первые символы равны, то таким же образом сравниваются уже вторые символы строк.
  4. Сравнение продолжается, пока не закончится одна из строк.
  5. Если обе строки заканчиваются одновременно, то они равны. Иначе, большей считается более длинная строка.

В примерах выше сравнение ‘Я’ > ‘А’ завершится на первом шаге, тогда как строки «Кот» и «Код» будут сравниваться посимвольно:

  1. К равна К .
  2. о равна о .
  3. т больше чем д . На этом сравнение заканчивается. Первая строка больше.
Читать еще:  Параллельное программирование c

Приведённый выше алгоритм сравнения похож на алгоритм, используемый в словарях и телефонных книгах, но между ними есть и различия.

Например, в JavaScript имеет значение регистр символов. Заглавная буква «A» не равна строчной «a» . Какая же из них больше? Строчная «a» . Почему? Потому что строчные буквы имеют больший код во внутренней таблице кодирования, которую использует JavaScript (Unicode). Мы ещё поговорим о внутреннем представлении строк и его влиянии в главе Строки.

Сравнение разных типов

При сравнении значений разных типов JavaScript приводит каждое из них к числу.

Логическое значение true становится 1 , а false – 0 .

Возможна следующая ситуация:

  • Два значения равны.
  • Одно из них true как логическое значение, другое – false .

С точки зрения JavaScript, результат ожидаем. Равенство преобразует значения, используя числовое преобразование, поэтому «0» становится 0 . В то время как явное преобразование с помощью Boolean использует другой набор правил.

Строгое сравнение

Использование обычного сравнения == может вызывать проблемы. Например, оно не отличает 0 от false :

Та же проблема с пустой строкой:

Это происходит из-за того, что операнды разных типов преобразуются оператором == к числу. В итоге, и пустая строка, и false становятся нулём.

Как же тогда отличать 0 от false ?

Оператор строгого равенства === проверяет равенство без приведения типов.

Другими словами, если a и b имеют разные типы, то проверка a === b немедленно возвращает false без попытки их преобразования.

Ещё есть оператор строгого неравенства !== , аналогичный != .

Оператор строгого равенства дольше писать, но он делает код более очевидным и оставляет меньше мест для ошибок.

Сравнение с null и undefined

Поведение null и undefined при сравнении с другими значениями – особое:

При строгом равенстве ===

Эти значения различны, так как различны их типы.

Эти значения равны друг другу и не равны никаким другим значениям. Это специальное правило языка.

Значения null/undefined преобразуются к числам: null становится 0 , а undefined – NaN .

Посмотрим, какие забавные вещи случаются, когда мы применяем эти правила. И, что более важно, как избежать ошибок при их использовании.

Странный результат сравнения null и 0

Сравним null с нулём:

С точки зрения математики это странно. Результат последнего сравнения говорит о том, что » null больше или равно нулю», тогда результат одного из сравнений выше должен быть true , но они оба ложны.

Причина в том, что нестрогое равенство и сравнения > = работают по-разному. Сравнения преобразуют null в число, рассматривая его как 0 . Поэтому выражение (3) null >= 0 истинно, а null > 0 ложно.

С другой стороны, для нестрогого равенства == значений undefined и null действует особое правило: эти значения ни к чему не приводятся, они равны друг другу и не равны ничему другому. Поэтому (2) null == 0 ложно.

Несравнимое значение undefined

Значение undefined несравнимо с другими значениями:

Почему же сравнение undefined с нулём всегда ложно?

На это есть следующие причины:

  • Сравнения (1) и (2) возвращают false , потому что undefined преобразуется в NaN , а NaN – это специальное числовое значение, которое возвращает false при любых сравнениях.
  • Нестрогое равенство (3) возвращает false , потому что undefined равно только null и ничему больше.

Как избежать проблем

Зачем мы рассмотрели все эти примеры? Должны ли мы постоянно помнить обо всех этих особенностях? Не обязательно. Со временем все они станут вам знакомы, но можно избежать проблем, если следовать простому правилу.

Просто относитесь к любому сравнению с undefined/null , кроме строгого равенства === , с осторожностью.

Не используйте сравнения >= > с переменными, которые могут принимать значения null/undefined , если вы не уверены в том, что делаете. Если переменная может принимать эти значения, то добавьте для них отдельные проверки.

Урок №42. Операторы сравнения

Обновл. 29 Дек 2019 |

В C++ есть 6 операторов сравнения:

Сравнение чисел типа с плавающей точкой

Сравнение значений типа с плавающей точкой с помощью любого из этих операторов — дело опасное. Почему? Из-за тех самых небольших ошибок округления, которые могут привести к неожиданным результатам.

В программе выше, d1 = 0.0100000000000005116 , а d2 = 0.0099999999999997868 . Оба этих числа очень близки к 0.1 , но d1 больше d2 . Они не равны.

Иногда сравнение чисел типа с плавающей точкой бывает неизбежным. В таком случае следует использовать операторы > , , >= и только если значения не очень близки. А вот если два операнда очень близки по значениям, то результат уже может быть неожиданный. В примере выше последствия неправильного результата незначительны, а вот с оператором равенства дела обстоят хуже, так как даже при самой маленькой неточности результат сразу меняется на противоположный ожидаемому. Не рекомендуется использовать операторы == или != с числами типа с плавающей точкой. Вместо них лучше использовать функцию, которая вычисляет, насколько близки эти два числа. Если они «достаточно близки», то мы считаем их равными. Значение, используемое для представления термина «достаточно близки», называется эпсилон. Оно, обычно, небольшое (например, 0.0000001 ).

Очень часто начинающие разработчики пытаются писать свои собственные функции определения равенства чисел:

Хоть это и рабочий вариант, но он не идеален. Эпсилон 0.00001 подходит для чисел около 1.0, но будет слишком большим для чисел типа 0.0000001 и слишком малым для чисел типа 10 000. Это означает, что каждый раз, при вызове функции, нам нужно будет выбирать наиболее соответствующий входным данным функции эпсилон.

Дональд Кнут, известный учёный, предложил следующий способ в своей книге «Искусство программирования, том 2: Получисленные алгоритмы» (1968):

Второй вызов не сработал так, как ожидалось. Математика просто ломается, когда дело доходит до нулей.

Но и этого можно избежать, используя как абсолютный эпсилон (то, что мы делали в первом способе), так и относительный (способ Кнута) вместе:

С удачно подобранным absEpsilon , функция approximatelyEqualAbsRel() обрабатывает нулевые значения правильно.

Сравнение чисел типа с плавающей точкой — сложная тема, и нет одного идеального алгоритма, который подойдёт в любой ситуации. Однако, для большинства случаев, с которыми вы будете сталкиваться, функции approximatelyEqualAbsRel() должно быть достаточно.

Курсы «C#.NET Developer»

Курсы «Java Developer»

Курсы «Frontend Developer»

Курсы «JavaScript Developer»

Курсы «Python Developer»

Курсы «Unity/Game Developer»

Поделиться в социальных сетях:

Урок №41. Условный тернарный оператор, sizeof() и Запятая

Комментариев: 18

А почему нельзя взять взять за вычисляемый эпсилон среднее арифметическое абсолютных значений сравниваемых величин умноженное на эпсилон? Код вроде попроще будет.

Можно и так наверно, но мне кажется тут берется большее число, потому что всегда надо рассматривать худший случай

Если при сравнении чисел указать тип float вместо double, то результатом будет true, даже при обычном сравнении. Это специфика компилятора или есть еще что-то?

Я тоже заметил что float точный, думаю нужно просто запомнить что double и long double имеют такие костыли.

Возможно, вы удивитесь, но результат:

Второй вызов не сработал так, как ожидалось. Математика просто ломается, когда дело доходит до нулей.
Почему?

Потому что почти 1(допустим 0.9) — 1 = -0.1. Да это действительно меньше нуля и функция по логике должна возвращать true, но если посмотреть внимательнее можно заметить. что там берется модуль. То есть: fabs(-0.1) = 0.1, а это уже больше нуля

Тяжеловата тема, но интересно.
Наибольшая сложность — не знаешь сразу куда применять.

Тема интересная, но не сразу дается. Код понял «примерно» т.е. поверхностно, чует сердце, буду к нему еще возвращаться. Принцип понятен сразу: как в тестере крутилка: 2 вольта, 20 вольт, 200 вольт и т.д. Воспоминание о аналоговых входах МК меня немного огорчило: там как раз и надо сравнивать небольшие напряжения. Например АКБ -зарядился или нет, сел или еще пойдет… теперь понимаю, почему так часто врут индикаторы заряда батарей. Спасибо, очередной интересный урок!

Читать еще:  Язык программирования майкрософт

Пожалуйста Главное — не зацикливайтесь, если что — вернётесь позже к этому уроку.

интересно для написания торгового робота на криптобирже нужно применять функцию approximatelyEqualAbsRel() или нет?

Вы пишете ботов на С++ для криптобирж?

Первый урок, который я вообще не понял :). Видимо, из-за того, что не выспался. Код вообще не понятен. Пытаюсь — не выходит(

Алло, Дед Максим! Ты когда пишешь рукой на листочек строку текста и приближаешься к правому краю и видишь, что последнее слово (если будешь продолжать таким же почерком) не помещается в строку, что делаешь? Правильно. Прижимистей буквы друг к другу тулишь. Это аналоговое представление значений. Цифровое же (то, которое в ЭВМ) — это когда все знаки и расстояния между ними строго одинаковы. И теперь представь себе, что точность — это ширина листа (если листок в клеточку, вообще, идеальная аналогия цифрового представления значений!) И вот тебе надо сравнить заряд электрона и заряд бозона. Что надо сделать? Правильно! Взять листочки по-ширше, т е. установить по-больше точность, иначе не влезающие цифры пропадут и вместо сравниваемых значений вообще какая-то дурь осядет. Но это ещё пол-беды! Подоплёка машинных «мансов» в том, что ЭВМ втихаря дописывает в клеточки левые цифры для заполнения пустующих после значащих цифр клеточек. Ну естественно результаты сравнения 100 — 99.99 и 10 — 9.99 с такими мансами будут не корректными! Да, дык о чём это я? А, вот пример: Требуется сравнить две трёхлитровых банки с жидкостью (молоко, самогон — по вкусу:-). Задаёмся граничным условием — если разница залитых объёмов не превышает одну пипетку (эпсилон) принимаем объёмы как равные. Пипетка — это абсолютный эпсилон, а объём пипетки/объём банки — это относительный эпсилон. А если объёмы сопоставимы с пипеткой (близки нулю)? Тогда Гулливер ловит лилипута, аннексирует у него пипетку (absEpsilon) и если разница меньше этого absEpsilon, то значения объёмов за «ноль» сойдут — не похмелишься (не наешься)!

Радует то, что в реальной жизни чаще требуется сравнивать целые числа. А когда доходит до чисел с плавающей точкой, то там почти всегда не важно «>» или «>=».

Ну это в реальной жизни Та и в реальной жизни бывают исключения.

Кажется у меня отключился мозг после строчки: «Очень часто начинающие разработчики пытаются писать свои собственные функции определения равенства чисел:»

Операторы сравнения

Многие операторы сравнения известны нам из математики:

  • Больше/меньше: a > b , a .
  • Больше/меньше или равно: a >= b , a .
  • Равно: a == b . Обратите внимание, для сравнения используется двойной знак равенства = . Один знак равенства a = b означал бы присваивание.
  • Не равно. В математике обозначается символом ≠ . В JavaScript записывается как знак равенства с предшествующим ему восклицательным знаком: a != b .

Результат сравнения имеет логический тип

Операторы сравнения, как и другие операторы, возвращают значение. Это значение имеет логический тип.

  • true – означает «да», «верно», «истина».
  • false – означает «нет», «неверно», «ложь».

Результат сравнения можно присвоить переменной, как и любое значение:

Сравнение строк

Чтобы определить, что одна строка больше другой, JavaScript использует «алфавитный» или «лексикографический» порядок.

Другими словами, строки сравниваются посимвольно.

Алгоритм сравнения двух строк довольно прост:

  1. Сначала сравниваются первые символы строк.
  2. Если первый символ первой строки больше (меньше), чем первый символ второй, то первая строка больше (меньше) второй.
  3. Если первые символы равны, то таким же образом сравниваются уже вторые символы строк.
  4. Сравнение продолжается, пока не закончится одна из строк.
  5. Если обе строки заканчиваются одновременно, то они равны. Иначе, большей считается более длинная строка.

В примерах выше сравнение ‘Я’ > ‘А’ завершится на первом шаге, тогда как строки «Кот» и «Код» будут сравниваться посимвольно:

  1. К равна К .
  2. о равна о .
  3. т больше чем д . На этом сравнение заканчивается. Первая строка больше.

Приведённый выше алгоритм сравнения похож на алгоритм, используемый в словарях и телефонных книгах, но между ними есть и различия.

Например, в JavaScript имеет значение регистр символов. Заглавная буква «A» не равна строчной «a» . Какая же из них больше? Строчная «a» . Почему? Потому что строчные буквы имеют больший код во внутренней таблице кодирования, которую использует JavaScript (Unicode). Мы ещё поговорим о внутреннем представлении строк и его влиянии в главе Строки.

Сравнение разных типов

При сравнении значений разных типов JavaScript приводит каждое из них к числу.

Логическое значение true становится 1 , а false – 0 .

Возможна следующая ситуация:

  • Два значения равны.
  • Одно из них true как логическое значение, другое – false .

С точки зрения JavaScript, результат ожидаем. Равенство преобразует значения, используя числовое преобразование, поэтому «0» становится 0 . В то время как явное преобразование с помощью Boolean использует другой набор правил.

Строгое сравнение

Использование обычного сравнения == может вызывать проблемы. Например, оно не отличает 0 от false :

Та же проблема с пустой строкой:

Это происходит из-за того, что операнды разных типов преобразуются оператором == к числу. В итоге, и пустая строка, и false становятся нулём.

Как же тогда отличать 0 от false ?

Оператор строгого равенства === проверяет равенство без приведения типов.

Другими словами, если a и b имеют разные типы, то проверка a === b немедленно возвращает false без попытки их преобразования.

Ещё есть оператор строгого неравенства !== , аналогичный != .

Оператор строгого равенства дольше писать, но он делает код более очевидным и оставляет меньше мест для ошибок.

Сравнение с null и undefined

Поведение null и undefined при сравнении с другими значениями – особое:

При строгом равенстве ===

Эти значения различны, так как различны их типы.

Эти значения равны друг другу и не равны никаким другим значениям. Это специальное правило языка.

Значения null/undefined преобразуются к числам: null становится 0 , а undefined – NaN .

Посмотрим, какие забавные вещи случаются, когда мы применяем эти правила. И, что более важно, как избежать ошибок при их использовании.

Странный результат сравнения null и 0

Сравним null с нулём:

С точки зрения математики это странно. Результат последнего сравнения говорит о том, что » null больше или равно нулю», тогда результат одного из сравнений выше должен быть true , но они оба ложны.

Причина в том, что нестрогое равенство и сравнения > = работают по-разному. Сравнения преобразуют null в число, рассматривая его как 0 . Поэтому выражение (3) null >= 0 истинно, а null > 0 ложно.

С другой стороны, для нестрогого равенства == значений undefined и null действует особое правило: эти значения ни к чему не приводятся, они равны друг другу и не равны ничему другому. Поэтому (2) null == 0 ложно.

Несравнимое значение undefined

Значение undefined несравнимо с другими значениями:

Почему же сравнение undefined с нулём всегда ложно?

На это есть следующие причины:

  • Сравнения (1) и (2) возвращают false , потому что undefined преобразуется в NaN , а NaN – это специальное числовое значение, которое возвращает false при любых сравнениях.
  • Нестрогое равенство (3) возвращает false , потому что undefined равно только null и ничему больше.

Как избежать проблем

Зачем мы рассмотрели все эти примеры? Должны ли мы постоянно помнить обо всех этих особенностях? Не обязательно. Со временем все они станут вам знакомы, но можно избежать проблем, если следовать простому правилу.

Просто относитесь к любому сравнению с undefined/null , кроме строгого равенства === , с осторожностью.

Не используйте сравнения >= > с переменными, которые могут принимать значения null/undefined , если вы не уверены в том, что делаете. Если переменная может принимать эти значения, то добавьте для них отдельные проверки.

Ссылка на основную публикацию
Adblock
detector