Skip to content

Commit 6cd0b4a

Browse files
committed
Новая версия урока 4.3
1 parent 8614b6a commit 6cd0b4a

File tree

4 files changed

+80
-19
lines changed

4 files changed

+80
-19
lines changed

lang_c/4/2__prioritet_operaciy/article.md

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,32 @@
11
# Приоритет операций. Cложные математические выражения
22

3-
В математических вычислениях важную роль играет порядок, в котором выполняются действия. Чему, например, равно значение выражения `2 + 2 * 2`? Старый школьный прикол. Конечно же шесть, т.к. сначала выполняется умножение.
3+
В математических вычислениях важную роль играет порядок, в котором выполняются действия. Вспомним старый школьный прикол. Сколько будет `2 + 2 * 2`? Конечно же шесть, т.к. сначала выполняется умножение.
44

5-
В C используется знакомый нам со школы порядок выполнения операций. Но т.к. в программировании есть свои особенности, то кое-какие отличия всё же есть.
5+
В C используется знакомый нам со школы порядок действий. Но т.к. в программировании есть свои особенности, то кое-какие отличия всё же есть.
66

77
Выпишем приоритет для тех операций, которые мы уже знаем.
88

9-
1. вызов и вычисление функций (например, `sqrt()`, `cos()` и пр.)
10-
2. умножение, деление, остаток от деления
11-
3. сложение, вычитание
12-
4. выполняется присваивание
9+
1. явное приведение типов
10+
2. вызов и вычисление функций (например, `sqrt()`, `cos()` и пр.)
11+
3. умножение, деление, остаток от деления
12+
4. сложение, вычитание
13+
5. выполняется присваивание
14+
1315

14-
Каково значение переменных `x` и `y` после выполнения следующего кода `int x = 8 / 4 * 2;`?
16+
Давайте себя проверим. Какое значение будет записано в переменную `x` после выполнения следующей строки кода `int x = 8 / 4 * 2;`?
1517

16-
Правильный ответ `4`. Т.к все операторы `/` и `*`, присутствующие в выражении, имеют одинаковы приоритет, то действия выполняются слева направо. Другими словами данный код эквивалентен коду `int x = (8 / 4) * 2;`
18+
Правильный ответ `4`. Т.к все операторы `/` и `*`, присутствующие в выражении, имеют одинаковыq приоритет, то действия выполняются слева направо. Другими словами данный код эквивалентен коду `int x = (8 / 4) * 2;`
1719

18-
Здесь я использовал =круглые группирующие скобки `()`= для того, чтобы явно указать, что деление должно быть выполнено первым действием. Использование скобок для изменения порядка выполнения вычислений скорее всего уже хорошо вам известно со школы.
20+
Здесь я использовал =круглые группирующие скобки `()`= для того, чтобы явно указать, что деление должно быть выполнено первым действием. Использование скобок для изменения порядка действий скорее всего уже хорошо вам известно со школы.
1921

2022
Давайте дополним нашу таблицу приоритетов операций скобками:
2123

2224
1. действия в скобках `()`
23-
2. вызов и вычисление функций (например, `sqrt()`, `cos()` и пр.)
24-
3. умножение, деление, остаток от деления
25-
4. сложение, вычитание
26-
5. выполнение присваивания
25+
2. явное приведение типов
26+
3. вызов и вычисление функций (например, `sqrt()`, `cos()` и пр.)
27+
4. умножение, деление, остаток от деления
28+
5. сложение, вычитание
29+
6. выполнение присваивания
2730

2831
Листинг 1.
2932
```c
@@ -34,10 +37,9 @@
3437
% **Важно!**
3538
Если в вашей программе вы написали довольно сложное выражение, в котором не сразу ясен порядок операций, то лучше добавить лишние скобки, чтобы явно задать последовательность операций. Это поможет избежать ошибок в вычислениях, которые потом будет сложно отловить.
3639

37-
3840
Кстати, а чему равняется значение `x` для следующего выражения: `int x = 1 / 2 * 2 + 1`?
3941

40-
Кто сказал `2`? Не правильно! Уже догадались почему? Нет, с приоритетами тут всё как надо. Если расставить скобки, то получим следующее эквивалентное выражение `int x = ((1 / 2) * 2) + 1`.
42+
Кто сказал `2`? Не правильно! Уже догадались почему? Нет, с приоритетами тут всё хорошо. Если расставить скобки, то получим следующее эквивалентное выражение `int x = ((1 / 2) * 2) + 1`.
4143

4244
Да, верно, проблема в том, что деление-то целочисленное, а значит `1 / 2` даст `0`, а значит `0 * 2 = 0`. И в итоге правильный ответ `1`. Вывод: Не забывайте про особенности целочисленного деления.
4345

@@ -46,9 +48,9 @@
4648

4749
Формулы для вычислений бывают довольно громоздкими.
4850

49-
При этом, когда мы пишем программу, любое выражение мы записываем в одну строку. На начальном этапе это может вызвать некоторые затруднения. Чтобы от них избавиться, нужно овладеть навыком переводить формулу из стандартной математической записи в ту, которая используется в программировании и обратно.
51+
При этом, когда мы пишем программу, любое выражение, даже если в нём присутствуют дроби (в том числе и многоуровневые), мы записываем в строчку. На начальном этапе это может вызвать некоторые затруднения. Чтобы от них избавиться, нужно овладеть навыком переводить формулу из стандартной математической записи в ту, которая используется в программировании и обратно.
5052

51-
В следующем небольшом видео я на простом примере показываю, как можно поступать при записи сложных математических выражений.
53+
В следующем небольшом видео на простом примере показаны несколько подходов, позволяющих не запутаться при записи сложных математических выражений.
5254

5355
<div class="lessonVideo">
5456
<iframe src="https://www.youtube.com/embed/Gx6KUtmRmHs" allowfullscreen></iframe>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"title": "Приоритет операций и запись сложных математических выражений",
3-
"description": "В уроке описаны основные сведения о приоритете операций в языке Си. Показано несколько приёмов, которые помогают не допустить ошибок, при записи сложных математических выражений.",
3+
"description": "В уроке даны основные сведения о приоритетах выполнения базовых операций в языке Си. Показано несколько приёмов, которые помогают не допустить ошибок, при записи сложных математических выражений.",
44
"keywords": "приоритет операций, запись сложных математических выражений",
55
"canonical_link": "https://youngcoder.ru/lessons/4/prioritet_operaciy"
66
}

lang_c/4/2__prioritet_operaciy/practice.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,37 @@
77
</div>
88

99

10-
- Пусть даны три целочисленные переменные `int a = 5, b = 7, c = 9;`. Почему выражения `(double)c/(b/a)` и `c/((double)b/a)` имеют разный результат? Своё объяснение напишите в комментариях к этому уроку.
10+
- Иногда из-за особенностей выполнения арифметических действия и преобразований некоторые математические истины "перестают работать". Разберитесь, почему следующие программы выдают различные результаты:
11+
12+
```c
13+
#include <stdio.h>
14+
15+
int main(void)
16+
{
17+
18+
int a = 8, b = 16, c = 2;
19+
20+
int res_1 = a / b * c;
21+
int res_2 = a * c / b;
22+
23+
printf("1: %d\n2: %d\n", res_1, res_2);
24+
return 0;
25+
}
26+
```
27+
28+
```c
29+
#include <stdio.h>
30+
31+
int main(void)
32+
{
33+
34+
int a = 5, b = 7, c = 9;
35+
36+
double res_1 = (double) c / (b / a);
37+
double res_2 = c / ((double) b / a);
38+
39+
printf("1: %.2f\n2: %.2f\n", res_1, res_2);
40+
return 0;
41+
}
42+
```
43+
Ваши объяснения этих "парадоксов" пишите в комментариях к этому уроку.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,28 @@
11
## Дополнительные материалы
22

3+
1\. Для понимания структуры выражений (да и всего кода в целом) компилятор строит специальную древовидную структуру, называемую =абстрактным синтаксическим деревом (Abstract Syntax Tree, AST)=.
4+
5+
Например, для выражения `int num = 3 + a * 5;` такое дерево может выглядеть следующим образом:
6+
7+
```
8+
=
9+
/ \
10+
num +
11+
/ \
12+
3 *
13+
/ \
14+
a 5
15+
```
16+
17+
Компилятор не рисует такие рисуночки (их называют =графы=), а использует для этого специальные структуры данных. Но нам, конечно, удобнее воспринимать визуальное представление.
18+
19+
Важно отметить, что структура AST напрямую отражает приоритет операций: операции с более высоким приоритетом (например, умножение) располагаются ближе к листьям дерева (значения и перменные), чем операции с меньшим приоритетом (например, сложение).
20+
21+
Такие деревья используются компилятором для:
22+
- Оптимизации и упрощения выражений
23+
- Удаления ненужных вычислений
24+
- Переупорядочивания операций для большей эффективности
25+
- Генерации эффективного машинного кода
26+
- Обнаружения синтаксических ошибок
27+
28+
Подобные структуры изучаются в рамках Теоретической информатики (Computer Science) в курсах по "Формальным языкам и грамматикам".

0 commit comments

Comments
 (0)