Переменные, Типы данных и Преобразование типов - Язык программирования C++ для спортивного программирования
Неделя 1Первая программа, Ввод/вывод и арифметика, Типы данных и их преобразование
Переменные, Типы данных и Преобразование типов
Переменные как коробки с этикетками, шесть типов и когда какой использовать, а также почему 7 / 2 равно 3, а большая сумма становится отрицательной, — преобразование в нужный тип до вычисления. Затем — каким большим может стать ответ, чтение и печать действительных чисел и математические функции (abs, min, max, sqrt, ceil…), нужные для практики.
Теория
Урок 5 из 7
20 мин чтения
Вопросов: 13
Прежде чем программа сможет напечатать Hello, Ali, ей нужно где-то хранить
Ali. Прежде чем сложить баллы, ей нужно где-то хранить текущую сумму. Это
«где-то» называется переменной.
Переменная — это коробка с этикеткой
Представьте ряд коробок на полке. На каждой спереди этикетка — её имя, — а
внутри что-то лежит — её значение. Когда программа упоминает score, она
заглядывает в коробку с этикеткой score и берёт то, что лежит там в этот
момент.
У каждой коробки есть ещё и тип, который задаётся при её создании: в коробку
для целых чисел не положишь слово, а в коробку для одной буквы — предложение.
Пройдите по шагам, как несколько коробок заполняются и перезаполняются:
Переменные — это коробки: смотрим, как меняются значения
C++
1#include <bits/stdc++.h>
2using namespace std;
3
4int main() {
5 int score = 10;score= 10
6 score = score + 5;
7 int bonus = 3;
8 score = score + bonus;
9 double height = 1.62;
10 cout << score << " " << height << "\n";
11 return 0;
12}
Объявляем и заполняем
строка 5
int score = 10 делает три дела сразу: создаёт коробку, называет её score и кладёт в неё 10.
score10bonus—height—
нажми пуск
1 / 6
Отсюда два вывода. Строка вроде score = score + 5 читается справа налево:
вычислить score + 5 со значением, которое лежит в коробке сейчас, и положить
результат обратно. И изменение одной коробки никогда не меняет другую — в
bonus так и осталось 3.
Как создать коробку
Одна строка, три части: тип (int), имя (age) и начальное
значение (= 13). Можно сначала создать коробку, а заполнить потом — именно
так и бывает, когда значение приходит из cin:
Пока в такую коробку ничего не положили, в ней лежит то, что случайно осталось в
этом участке памяти. Поэтому давайте каждой переменной значение — через или
через — прежде чем её использовать.
дальше
Практика: Большие целые числа
Четырнадцать задач с целыми числами, некоторые из которых слишком велики для int.
Несколько коробок одного типа можно создать в одной строке:
int width = 10, height = 5;.
Как назвать коробку
Только буквы, цифры и _ — без пробелов и без -.
Имя не может начинаться с цифры: place2 можно, 2place нельзя.
Заглавные буквы важны: score и Score — две разные коробки.
Нельзя брать слово, которое уже занято в C++, например int или return.
Помимо правил, выбирайте имена, которые говорят, для чего коробка. total
что-то сообщает следующему читателю; t заставляет его вернуться и разбираться.
Типы, которыми вы будете пользоваться
Тип
Хранит
Пример
int
Целые числа, примерно ±2,1 миллиарда
int age = 13;
long long
Очень большие целые числа, примерно ±9,2 × 10¹⁸
long long views = 9000000000;
double
Числа с дробной частью
double height = 1.62;
char
Один символ, в одинарных кавычках
char grade = 'A';
string
Текст любой длины, в двойных кавычках
string name = "Ali";
bool
true или false
bool ready = true;
Что стоит знать о каждом:
int заканчивается ровно на 2 147 483 647. Этого хватает для
возраста, оценок и подсчётов — но не для всего, и для этого есть long long.
long long — ответ всякий раз, когда значение может превысить два
миллиарда. Большое число, записанное в него напрямую, — не проблема. Ловушка в
том, чтобы вычислять его из int поменьше, — это второй сюрприз и следующий
раздел.
double хранит около 15 значащих цифр. Как напечатать его так, как хочет
задача, — ниже, в разделе Действительные числа.
char и string похожи, но это разные вещи: 'A' — один символ, а
"A" — текст, который случайно состоит из одного символа. Пока оба нужны для
чтения и печати: char c; cin >> c; читает один символ (пропуская пробелы), а
string s; cin >> s; — одно слово. У обоих есть гораздо больше — char на
самом деле число, а string на самом деле ряд char, — и это будет позже в
курсе.
bool печатается как 1 для true и 0 для false. Он станет важен на
следующей неделе, когда программы начнут принимать решения.
Преобразование типов: объяснение двух сюрпризов
Прошлый урок закончился тем, что 7 / 2 печатает 3, а 2000000000 + 2000000000
— отрицательное число. Оба случая подчиняются одному правилу: C++ вычисляет
выражение в типе входящих в него значений и только потом кладёт ответ в
коробку. Коробка слева никак не влияет на то, как вычисляется правая часть.
Пройдите по шагам оба сюрприза в одной программе и проследите момент, когда
каждое значение перестаёт быть тем, что вы ожидали:
Две ловушки в одной программе — целочисленное деление и переполнение int
total и parts — оба int: целые числа, ничего после точки.
total7parts—share—exact—half—big—sum—safe—
предел int2 147 483 647предел long longоколо 9.2 × 10^18
нажми пуск
1 / 10
Значит, исправление всегда в правой части: сделайте одно из значений нужного
типа до того, как произойдёт вычисление.
Вы пишете (a равно 7, b равно 2)
Получаете
Потому что
a / b
3
оба int, поэтому деление целочисленное
double x = a / b;
3
деление уже произошло в int — слишком поздно
1.0 * a / b
3.5
1.0 * a — это double, значит, и деление тоже
(double)a / b или double(a) / b
3.5
сначала преобразует a, так же
int(3.9)
3
при переводе в int дробная часть отбрасывается в сторону нуля: int(-3.9) равно −3
1LL * a * b
произведение типа long long
умножение идёт в long long, поэтому переполниться не может
Последняя строка — это исправление второго сюрприза. int заканчивается на
2 147 483 647; если выйти за предел, значение переполняется и часто
становится отрицательным. Программа не останавливается и ни о чём не сообщает во
время работы — она просто продолжает с неправильным числом. Если ответ может
превысить два миллиарда, храните его в long longи выполняйте вычисление в
long long.
В какую коробку поместится?
Четыре значения. Для каждого выберите самый маленький тип, который правильно его
хранит, — а если ошибётесь, увидите, что на самом деле сохранит C++.
В какую коробку поместится?попробуй!
Каким большим может стать ответ?
Прежде чем писать код, посмотрите на ограничения в задаче и найдите самый
большой ответ, который она может потребовать. Коробку выбирает именно он, а не
размер входных данных.
Задача говорит
Самый большой ответ
Коробка
a, b и c до 10⁹; их сумма a + b + c
3 · 10⁹
long long — уже больше int
стороны до 10⁹; периметр 2 · (a + b)
4 · 10⁹
long long
a и b до 10⁹; вывести a × b
10¹⁸
long long
n до 10⁹ гигабайт, в битах: n · 8 · 1024³
8,6 · 10¹⁸
long long, впритык: предел 9,2 · 10¹⁸
Стоит запомнить два числа: int вмещает около 2 · 10⁹, long long — около
9 · 10¹⁸.
Затем проследите, чтобы само вычисление шло в long long. Проще всего читать
ввод в коробки long long: всё, что вычисляется из них, тоже будет
long long. Но следите за порядком — C++ считает слева направо, и часть в int
может переполниться раньше, чем встретит long long. Если n — long long со
значением 16:
/ и % работают с long long точно так же, как с int. Пройдите по шагам,
как триллион секунд раскладывается на дни, часы, минуты и секунды, — та же пара
операторов, по одной ступени за раз:
Ввод доходит до 10¹², далеко за пределы 2 147 483 647 у int, поэтому коробка с самого начала — long long.
ввод
1000000000000
t?days—rest—hours—minutes—seconds—
нажми пуск
1 / 9
Действительные числа: чтение, деление, печать
Чтение.double x; cin >> x; принимает и 1.5, и просто 3. Если во вводе
может быть дробная часть, читайте в double.
Деление. Правило вы знаете: хотя бы одна сторона должна быть doubleдо
деления. Оно прячется и внутри формул: в ⅖ · x² часть 2 / 5 в C++ равна 0 —
пишите 2.0 / 5. А int может переполниться внутри формулы ещё до того, как до
неё доберётся sqrt: если y — int со значением 10⁹, то 5 * y уже неверно, а
5.0 * y — нормально.
Квадраты перед корнем. Расстояние — это sqrt(dx * dx + dy * dy). Если
координаты по модулю до 10⁹, dx может достигать 2 · 10⁹, а dx * dx —
4 · 10¹⁸, поэтому храните их в long long (или double), прежде чем возводить
в квадрат.
Печать. По умолчанию cout показывает только 6 значащих цифр: значение
1414213562.37 выводится как 1.41421e+09, а это «Неправильный ответ». Исправляют
это два инструмента:
Вы пишете
Это значит
1414213562.37 печатается как
cout << x;
6 значащих цифр
1.41421e+09
cout << setprecision(4) << x;
4 значащие цифры
1.414e+09
cout << fixed << setprecision(2) << x;
ровно 2 цифры после точки
1414213562.37
С fixed число означает знаки после запятой — а именно это и спрашивают задачи.
Напишите cout << fixed << setprecision(10); один раз в начале программы,
которая печатает действительные числа, или укажите столько знаков, сколько
требует задача.
float или double? В C++ есть тип поменьше, float, который хранит только
около 7 цифр: float f = 16777217; сохраняет 16777216. Всегда используйте
double.
Константы. Значение, которое никогда не меняется, можно пометить const, и
тогда его нельзя изменить по ошибке:
Полезные математические функции
Все они подключаются через #include <bits/stdc++.h>:
Функция
Что делает
Пример
abs(x)
расстояние до нуля
abs(-7) равно 7, abs(-2.5) — 2.5
min(a, b), max(a, b)
меньшее и большее из двух значений
max(4, max(9, 7)) равно 9 — для трёх вкладывайте
sqrt(x)
квадратный корень, как double
sqrt(2.0) равно 1.41421…
pow(a, b)
a в степени b, как double
pow(2, 10) равно 1024
ceil(x), floor(x), round(x)
округление вверх, вниз, до ближайшего
ceil(3.2) равно 4, floor(3.8) — 3, round(2.5) — 3
Две ловушки, обе из правила этого урока:
ceil(7 / 2) равно 3: 7 / 2 сначала вычисляется для двух int, и
округлять уже нечего. ceil(7 / 2.0) равно 4.
pow работает в double, который хранит около 15 цифр. pow(15, 15),
сохранённое в long long, равно 437893890380859392, а 15¹⁵ — это
437893890380859375. Для целых степеней умножайте.
Проверьте себя
А вы знали?
YouTube хранил число просмотров в 32-битном целом — того же размера, что int
в C++, и с тем же пределом 2 147 483 647. В декабре 2014 года компания
объявила, что Gangnam Style посмотрели столько раз, что счётчик пришлось
перевести на 64-битное целое — размером с long long. Её инженеры не ожидали,
что какому-то видео понадобится больше двух миллиардов.
int age = 13;
int age;cin >> age;
проверь себя1 балл
Какое самое большое число может хранить int?
Выберите один ответ
Войдите, чтобы ответить и сохранить прогресс.Войти
проверь себя1 балл
Что будет лежать в score после этих строк?
Войдите, чтобы ответить и сохранить прогресс.Войти
проверь себя1 балл
Чему равно int(3.9)?
Войдите, чтобы ответить и сохранить прогресс.Войти
проверь себя1 балл
double k = 2 / 5; — чему равно k?
Войдите, чтобы ответить и сохранить прогресс.Войти
проверь себя1 балл
Чему равно ceil(7 / 2)?
Войдите, чтобы ответить и сохранить прогресс.Войти
проверь себя1 балл
Какой тип подходит для цены вроде 9.99?
Выберите один ответ
Войдите, чтобы ответить и сохранить прогресс.Войти
проверь себя1 балл
Что из этого — char?
Выберите один ответ
Войдите, чтобы ответить и сохранить прогресс.Войти
проверь себя1 балл
Какое из этих имён переменной недопустимо?
Выберите один ответ
Войдите, чтобы ответить и сохранить прогресс.Войти
проверь себя1 балл
В a лежит 7, в b — 2, обе int. Что из этого даёт 3.5?
Выберите один ответ
Войдите, чтобы ответить и сохранить прогресс.Войти
проверь себя1 балл
a и b — int, в обеих лежит 100000. Какая строка правильно сохраняет их произведение, 10 000 000 000?
Выберите один ответ
Войдите, чтобы ответить и сохранить прогресс.Войти
проверь себя1 балл
a, b и c могут быть до 10⁹ каждое. Какой тип подходит для a + b + c?
Выберите один ответ
Войдите, чтобы ответить и сохранить прогресс.Войти
проверь себя1 балл
double x = 1414213562.37; Что напечатает cout << x;?
Выберите один ответ
Войдите, чтобы ответить и сохранить прогресс.Войти