Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 45 additions & 16 deletions modules/45-logic/10-bool-type/ru/README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,63 @@
В JavaScript есть специальный тип данных — **boolean** (булев тип). Он содержит только два значения: `true` (истина) и `false` (ложь).
Кроме арифметических операций, в математике есть операции сравнения, например `5 > 4` или `3 < 1`. Они есть и в программировании. Сравнения часто применяются в реальных задачах. Например, когда мы оформляем покупку в интернет-магазине, система проверяет, хватает ли у пользователя денег на счёте: если сумма на счёте больше или равна цене товара, заказ подтверждается, иначе появляется сообщение о нехватке средств.

## Операторы сравнения
## Сравнение в программировании

Операторы сравнения возвращают булево значение:
Начнём с примера, в котором сравниваются два числа:

```javascript
console.log(5 > 3); // => true
console.log(5 < 3); // => false
console.log(5 === 5); // => true
console.log(5 !== 3); // => true
console.log(5 > 4); // => true
console.log(4 > 4); // => false
```

Результатом сравнения является значение типа **boolean** (булев тип). У него всего два возможных значения: `true` (истина) и `false` (ложь). Это специальные значения языка, их можно использовать напрямую:

```javascript
console.log(true);
console.log(false);
```

На практике так их используют редко, но на их основе строится вся логика поведения программы. Мы сталкиваемся с этим каждый день: вводим пин-коды и пароли, выполняем действия, результат которых может быть разным. Программа рассуждает примерно так: *если так — делай раз, если иначе — делай два*.

В JavaScript доступны следующие операции сравнения:

| Оператор | Смысл |
|----------|-------|
| `>` | больше |
| `<` | меньше |
| `>=` | больше или равно |
| `<=` | меньше или равно |
| `>` | больше |
| `>=` | больше или равно |
| `===` | строго равно |
| `!==` | строго не равно |

## Функции, возвращающие boolean
Языки программирования переняли математические операции сравнения почти без изменений, кроме равенства и неравенства. В математике используется обычное `=`, но в программировании символ `=` уже занят — он присваивает переменным значения. Поэтому для сравнения на равенство в JavaScript используют `===`, а на неравенство — `!==` (тройной и с восклицательным знаком — это «строгое» сравнение, к которому мы ещё вернёмся).

```javascript
console.log(5 >= 3); // => true
console.log(7 < 0); // => false
console.log(5 > 5); // => false
console.log(5 >= 5); // => true
console.log(2 === 5); // => false
console.log(2 !== 5); // => true
```

Когда в сравнении используют конкретные значения, операция кажется бессмысленной: результат и так известен и всегда одинаков. Но всё меняется, когда значения могут быть разными. Напишем простую функцию, которая принимает возраст ребёнка и определяет, младенец ли он. Младенцами считаются дети до двух лет (два не включается):

```javascript
const isInfant = (age) => age < 2;

console.log(isInfant(3)); // => false
console.log(isInfant(2)); // => false
console.log(isInfant(1)); // => true
console.log(isInfant(0)); // => true
```

## Предикаты

Функции, возвращающие `true` или `false`, называют **предикатами**. По соглашению их называют с приставкой `is`, `has`, `can`:
Когда функции возвращают результат сравнения, они обычно отвечают на вопрос «да» или «нет». Такие функции называют **предикатами**. Их легко узнать: они возвращают логическое значение `true` или `false`, а в их названии часто есть проверяемое утверждение (`is`, `has`, `can`). Вот функция, проверяющая, является ли число отрицательным:

```javascript
function isPensioner(age) {
return age >= 60;
}
const isNegative = (number) => number < 0;

console.log(isPensioner(65)); // => true
console.log(isPensioner(30)); // => false
console.log(isNegative(-5)); // => true
console.log(isNegative(7)); // => false
```
2 changes: 2 additions & 0 deletions modules/45-logic/17-bool-strings/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
test:
@ test.sh
5 changes: 5 additions & 0 deletions modules/45-logic/17-bool-strings/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// BEGIN
const isLongWord = (word) => word.length > 5;
// END

export default isLongWord;
8 changes: 8 additions & 0 deletions modules/45-logic/17-bool-strings/ru/EXERCISE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
При регистрации на сайте программа проверяет, что пароль достаточно длинный — больше 5 символов. Напишите функцию `isLongWord()`, которая возвращает `true`, если длина переданного слова больше 5 символов, и `false` в противном случае.

Пример работы:

```javascript
isLongWord('apple'); // => false
isLongWord('banana'); // => true
```
53 changes: 53 additions & 0 deletions modules/45-logic/17-bool-strings/ru/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
Операции сравнения работают не только с числами, но и со строками. В JavaScript строки сравниваются лексикографически: посимвольно слева направо по числовым кодам символов (Unicode).

```javascript
console.log('apple' < 'banana'); // => true
console.log('cat' > 'dog'); // => false
console.log('abc' === 'abc'); // => true
console.log('hello' !== 'world'); // => true
```

Здесь `'apple' < 'banana'`, потому что код символа `a` (97) меньше кода `b` (98), и именно первый различающийся символ решает исход сравнения. Узнать код символа можно методом `charCodeAt()`:

```javascript
console.log('a'.charCodeAt(0)); // => 97
console.log('b'.charCodeAt(0)); // => 98
```

Сравнение чувствительно к регистру: код `'Z'` (90) меньше кода `'a'` (97). Несколько примеров, где первые буквы в разном регистре:

```javascript
console.log('Zebra' < 'apple'); // => true — 'Z'(90) < 'a'(97)
console.log('apple' < 'Banana'); // => false — 'a'(97) > 'B'(66)
console.log('Apple' < 'apple'); // => true — 'A'(65) < 'a'(97)
```

Напишем функцию, которая проверяет, начинается ли слово с заданной буквы. Для этого возьмём первый символ строки и сравним его с нужной буквой:

```javascript
const startsWithLetter = (word, letter) => word[0] === letter;

console.log(startsWithLetter('apple', 'a')); // => true
console.log(startsWithLetter('banana', 'a')); // => false
```

Операции сравнения — такие же выражения, как и арифметические. В них можно подставлять готовые значения и другие выражения, например `word[0]` выше. Можно использовать и свойство `.length`:

```javascript
console.log('apple'.length > 3); // => true, потому что длина равна 5
console.log('hi'.length > 3); // => false, потому что длина равна 2
```

Сначала вычисляется `'apple'.length` (получается число `5`), а потом это число сравнивается с `3`. То есть сначала считаются операнды выражения, а затем выполняется сравнение.

## Полезные предикаты

У строк в JavaScript есть встроенные методы-предикаты. Они возвращают `true` или `false` и помогают проверять разные свойства строки:

```javascript
console.log('hello'.startsWith('he')); // => true — строка начинается с 'he'
console.log('hello'.endsWith('lo')); // => true — строка заканчивается на 'lo'
console.log('hello'.includes('ell')); // => true — строка содержит 'ell'
```

Такие методы позволяют проверять строки на нужные условия прямо в коде, без написания дополнительных функций.
11 changes: 11 additions & 0 deletions modules/45-logic/17-bool-strings/ru/data.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
name: Сравнение строк
tips:
- >
[Сравнение строк в
JavaScript](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/Less_than)
definitions:
- name: Лексикографическое сравнение
description: >-
сравнение строк посимвольно слева направо по числовым кодам символов
(Unicode).
10 changes: 10 additions & 0 deletions modules/45-logic/17-bool-strings/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// @ts-check

import { expect, test } from 'vitest';
import f from './index.js';

test('test', () => {
expect(f('apple')).toBe(false);
expect(f('banana')).toBe(true);
expect(f('pineapple')).toBe(true);
});
65 changes: 60 additions & 5 deletions modules/45-logic/28-logical-negation/ru/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
Наряду с логическими операторами **И** (`&&`) и **ИЛИ** (`||`), часто используется операция «**отрицание**». Она меняет логическое значение на противоположное. В JavaScript отрицанию соответствует унарный оператор `!`:

Наряду с конъюнкцией (И) и дизъюнкцией (ИЛИ), часто используется операция «отрицание». Отрицание меняет логическое значение на противоположное. В программировании ему соответствует унарный оператор `!`.
```javascript
!true; // false
!false; // true
```

Если есть функция, проверяющая чётность числа, то с помощью отрицания можно выполнить проверку нечётности:
Например, если есть функция, проверяющая чётность числа, то с помощью отрицания можно выполнить проверку нечётности:

```javascript
const isEven = (number) => number % 2 === 0;
Expand All @@ -10,14 +14,65 @@ isEven(10); // true
!isEven(10); // false
```

То есть мы просто добавили `!` слева от вызова функции и получили обратное действие.
Мы просто добавили `!` слева от вызова функции и получили обратное действие. Отрицание позволяет выражать задуманные правила в коде без написания новых функций.

Отрицание — мощный инструмент, который позволяет лаконично выражать задуманные правила в коде без необходимости писать новые функции.
## Двойное отрицание

А что если написать так `!!isEven(10)`? Внезапно, но код сработает. В логике двойное отрицание подобно отсутствию отрицания вообще.
А что, если написать `!!isEven(10)`? Внезапно, но код сработает. В логике двойное отрицание равносильно отсутствию отрицания:

```javascript
isEven(10); // true
!isEven(10); // false
!!isEven(10); // true
```

## Комбинирование с && и ||

`!` можно комбинировать с `&&` и `||`. Среди логических операторов у отрицания наивысший приоритет, поэтому оно применяется первым:

```javascript
!true || true; // (!true) || true => false || true => true
!true && false; // (!true) && false => false && false => false
```

Скобки меняют порядок вычисления:

```javascript
!(true || true); // !true => false
!(true && false); // !false => true
```

Практический пример — функция проверяет, может ли водитель сесть за руль: нужны права и трезвость:

```javascript
const canDrive = (hasLicense, isDrunk) => hasLicense && !isDrunk;

console.log(canDrive(true, false)); // => true (есть права, трезвый)
console.log(canDrive(true, true)); // => false (есть права, но пьяный)
console.log(canDrive(false, false)); // => false (нет прав)
```

## Законы де Моргана

При работе со сложными логическими выражениями бывает нужно инвертировать их или переписать в эквивалентную, более читаемую форму. Для этого существуют **законы де Моргана** — два правила, описывающих, как отрицание распределяется по составному выражению:

```javascript
!(a && b) === !a || !b
!(a || b) === !a && !b
```

Первый закон: отрицание конъюнкции равно дизъюнкции отрицаний. Проверим:

```javascript
!(true && false); // !false => true
!true || !false; // false || true => true
```

Второй закон: отрицание дизъюнкции равно конъюнкции отрицаний:

```javascript
!(true || false); // !true => false
!true && !false; // false && true => false
```

На практике законы де Моргана помогают упрощать условия. Например, вместо `!(isAdmin || isModerator)` можно написать `!isAdmin && !isModerator` — читается как «не администратор и не модератор».
Loading