Введение: зачем нужны числа в программировании
Числа — это фундамент любого программирования. Почти все задачи, которые можно встретить в реальной жизни и в программных продуктах, так или иначе связаны с работой с числами: подсчётом денег, обработкой дат и времени, измерением расстояния, вычислениями в научных задачах и даже анализом текста.
В C++ числа используются для различных задач:
- хранения возраста пользователя, количества товаров, результата вычислений;
- сложения, вычитания, деления, умножения значений;
- сравнения (например, проверить, больше ли одно значение другого);
- преобразования данных (например, перевод градусов Цельсия в Фаренгейты).
В языке программирования C++ есть несколько видов числовых данных, которые позволяют удобно и правильно представлять и использовать разные типы чисел: от простых целых до дробных с высокой точностью.
Перед тем как начать изучать типы чисел, запомни: правильный выбор числового типа важен для эффективности и корректности программы.
В этом и следующих разделах мы научимся создавать переменные для разных числовых типов, производить с ними основные действия и разберёмся, как избегать типичных ошибок новичков.
Основные числовые типы данных в C++ — подробное объяснение и когда использовать
В C++ для хранения чисел используются разные типы, каждый предназначен для определённых целей. Очень важно понять, какой тип выбрать, чтобы программа работала правильно и эффективно.
Целочисленные типы (хранят только целые числа)
| Тип | Размер памяти (примерно) | Диапазон значений (пример) | Когда использовать? |
|---|---|---|---|
|
4 байта | От -2 147 483 648 до 2 147 483 647 | Большинство целых чисел (возраст, количество) |
|
2 байта | От -32 768 до 32 767 | Если нужно сэкономить память для маленьких чисел |
|
4 или 8 байт | Зависит от системы, обычно больше чем int |
Для больших целых чисел |
|
8 байт | Очень большие целые от −9 223 372 036 854 775 808 до 9 223 372 036 854 775 807 | Огромные числа: население, счётчики |
Знаковый и беззнаковый типы
signed (по умолчанию у всех целых) — могут содержать и положительные, и отрицательные числа.
unsigned — только положительные числа и ноль, но диапазон начинается с 0 и примерно в 2 раза больше по максимальному значению.
Например:
unsigned int money = 10000; // нельзя отрицательное, но можно больше по значению
int temperature = -10; // могут быть отрицательные значения
Используй unsigned, если точно знаешь, что числа не будут отрицательными (например, количество очков, количество предметов).
Вещественные типы (хранят числа с плавающей точкой — дробные числа)
| Тип | Размер памяти | Точность (пример) | Когда использовать? |
|---|---|---|---|
|
4 байта | Около 6 знаков после запятой | Для маленьких, не очень точных дробных чисел (например, температура). |
|
8 байт | Около 15 знаков после запятой | Когда нужна большая точность, например, вычисления с деньгами, научные вычисления. |
|
12–16 байт | Ещё выше точность | Очень точные вычисления, редко используется. |
Когда выбирать какой тип?
- Если работаешь с целыми числами (например, возраст, количество предметов) — выбирай
int. - Если числа могут быть очень большими (например, счётчики, население, секунды с начала эпохи) — смотри в сторону
long long. - Если числа не могут быть отрицательными — рассмотри
unsigned intдля увеличения максимального значения. - Для дробных чисел, если нужна высокая точность —
double, для простой и быстрой работы —float.
Примеры объявлений с комментариями
int age = 25; // возраст, целое число
unsigned int score = 1000; // баллы, только положительные
float temp = 36.6f; // температура тела, небольшой диапазон, не высокая точность
double distance = 12345.6789; // расстояние, большое число с дробной частью и большей точностью
long long population = 7800000000; // население мира, очень большое целое число
Обрати внимание: для
floatпосле числа добавляется букваf(например,36.6f), чтобы компилятор понял, что это именно типfloat, а неdouble.
Почему важен правильный выбор типа?
- Переменные занимают разное количество памяти.
- Неправильный тип может привести к ошибкам — например, если использовать
intдля очень большого числа, программа даст неверный результат. - Использование
unsignedбез необходимости может вызвать неожиданные ошибки, особенно при вычитании.
Задания для закрепления
1. Объяви переменную для хранения количества книг в библиотеке. Какой тип стоит выбрать —
intилиunsigned int? Почему?
2. Напиши объявление переменной для температуры воздуха с точностью до десятых долей — какой тип подходящий?
3. Объясни, почему нельзя хранить отрицательную температуру в переменной типа
unsigned int.
4. Объяви переменную для хранения миллиона секунд (1 000 000) — какой тип лучше и почему?
5. Напиши пример, где использование
doubleвместоfloatбудет важно.
Арифметические операции в C++
В программировании одним из главных действий с числами является выполнение арифметических операций: сложения, вычитания, умножения, деления и вычисления остатка от деления. В C++ эти операции очень похожи на те, что вы изучали в школьной математике, но у них есть особенности, связанные с типами данных.
Основные арифметические операции
-
Сложение (+): складывает два числа.
-
Вычитание (−): вычитает одно число из другого.
-
Умножение (*): перемножает числа.
-
Деление (/): делит одно число на другое. Важно помнить, что при делении целых чисел результат тоже будет целым числом (будет отброшена дробная часть).
-
Остаток от деления (%): показывает, что останется после деления целых чисел (только для целочисленных типов).
Примеры c комментариями
int a = 10; // объявляем целое число a равное 10
int b = 3; // объявляем целое число b равное 3
int sum = a + b; // сумма: 10 + 3 = 13
int diff = a - b; // разность: 10 - 3 = 7
int prod = a * b; // произведение: 10 * 3 = 30
int div = a / b; // целочисленное деление: 10 / 3 = 3 (десятичная часть отброшена)
int mod = a % b; // остаток от деления: 10 % 3 = 1
float fd = 10.0f / 3.0f; // деление чисел с плавающей точкой: около 3.3333
Важные моменты
- Если разделить два целых числа, то получаем целое число (дробная часть «отбрасывается»).
- Для получения точного результата с дробной частью нужно использовать вещественные типы (
float,double). - Операция остатка от деления % предназначена только для целых чисел
Основные функции для округления:
-
round()— округляет число до ближайшего целого. -
ceil()— округляет вверх (до ближайшего большего целого). -
floor()— округляет вниз (до ближайшего меньшего целого). -
setprecision()— задает число знаков после запятой при выводе.
Примеры:
#include <iostream>
#include <cmath> // для функций round, ceil, floor
#include <iomanip> // для setprecision
void main() {
double num = 3.14159;
std::cout << "Исходное число: " << num << std::endl;
std::cout << "округление round(): " << round(num) << std::endl; // 3
std::cout << "округление ceil(): " << ceil(num) << std::endl; // 4
std::cout << "округление floor(): " << floor(num) << std::endl; // 3
// Округление и вывод с нужным количеством знаков
std::cout << "Округление с 2 знаками после запятой:
";
std::cout << std::setprecision(3) << std::fixed << num << std::endl; // 3.14
// Округление до 2 знаков после запятой
double preciseNum = round(num * 100.0) / 100.0;
std::cout << "Округление до 2 знаков: " << preciseNum << std::endl; // 3.14
}
setprecisionвместе сfixedуправляет только выводом числа — сколько знаков после запятой будет показано, но не меняет само число в памяти.roundфактически изменяет значение числа, производя округление. Это важно, если дальше с этим числом делать вычисления или сохранять.
Что такое fixed?
fixed — это особый манипулятор для потоков вывода, который переключает вывод чисел с плавающей точкой в фиксированный десятичный формат (обычный десятичный, а не научный).
Это полезно, чтобы числа выглядели одинаково и удобно, например, при выводе валюты или результатов с фиксированным количеством знаков после запятой.
Пример:
#include <iostream>
#include <iomanip>
void main() {
double pi = 3.14159;
std::cout << "Без fixed: " << std::setprecision(5) << pi << std::endl; // 3.1416 или научная запись
std::cout << "С fixed: " << std::fixed << std::setprecision(5) << pi << std::endl; // 3.14159
double largeNum = 123456789.0;
std::cout << "Без fixed: " << largeNum << std::endl; // Может быть научная нотация
std::cout << "С fixed: " << std::fixed << largeNum << std::endl; // Обычная десятичная запись
}
В C++ операция остатка от деления % работает только с целыми типами. Если попытаться использовать % с дробными числами, например 5 % 2.5, компилятор выдаст ошибку.
Для вычисления остатка от деления дробных чисел используется специальная функция fmod, которая находится в заголовочном файле <cmath>.
#include <iostream>
#include <cmath> // для функции fmod
void main() {
double a = 5.0;
double b = 2.5;
double remainder = fmod(a, b); // вычисляем остаток для дробных чисел
std::cout << "Остаток от деления 5.0 на 2.5 равен " << remainder << std::endl;
}
Взаимодействие разных типов
Если в выражении участвуют разные типы (например, int и float), то происходит автоматическое преобразование типов — int преобразуется в float, и результат будет вещественным числом.
int i = 5;
float f = 2.5f;
float result = i + f; // i автоматически преобразуется в 5.0, сумма: 7.5
Задания для закрепления
6. Объяви две переменные целого типа и вычисли их сумму, разность, произведение, целочисленное деление и остаток от деления.
7. Повтори задание 1, но используй вещественные типы
floatилиdoubleи посмотри, как изменятся результаты.
8. Объясни, почему выражение
5 / 2даёт 2, а5.0 / 2— 2.5.
9. Напиши программу, которая вычисляет периметр прямоугольника с длиной и шириной типа
float.
10. Попробуй смешать в операции
intиfloat, посмотри что получится, и объясни результат.
11. Что произойдёт, если попытаться использовать оператор
%с дробными числами, например,5 % 2.5? Как правильно получить остаток от деления дробных чисел?
Явное указание типа переменной
В C++ тип переменной определяет, как происходит арифметика. Если указать тип неверно или неявно, можно получить неправильный результат.
Пример:
int a = 7; int b = 2; // Деление целых — результат тоже целый, дробная часть отбрасывается double result1 = a / b; // result1 = 3.0 // Явное преобразование чтобы получить дробный результат double result2 = static_cast<double>(a) / b; // result2 = 3.5Без явного преобразованияstatic_castделениеint / intпроисходит как целочисленное, и дробная часть теряется.
Преобразование типов (type casting)
Неявное преобразование
Компилятор автоматически повышает типы для правильной арифметики, например int к double.
int i = 5;
double d = 4.2;
double sum = i + d; // i автоматически преобразован в 5.0
Явное преобразование — static_cast
Используется для контроля преобразований и безопасности.
double d = 3.99;
int i = static_cast<int>(d); // i будет 3, дробная часть отбрасывается
Практические задания
12. Объяви переменные
int i = 3иdouble d = 4.5. Посчитай сумму с использованием и без использованияstatic_castдляi. Сравни результат.
13. Приведи число
3.99типаdoubleкintс помощьюstatic_cast. Объясни, что произошло с дробной частью.
14. Выполни деление
7 / 2и сохрани результат вdouble. Объясни, почему результат будет равен 3.0.
15. Перепиши вычисление из задачи 3 с помощью
static_castдля правильного результата.
16. Возьми число
3.14159. Выведи его двумя способами: с помощьюstd::fixed << std::setprecision(2), и округли реально с помощьюround(). Объясни разницу.
Типичные ошибки новичков при работе с числами в C++
В работе с числами многие начинающие встречаются с типичными сложностями, которые приводят к ошибкам. Обратим на них внимание и объясним, как их избежать.
Основные ошибки
- Деление целых чисел без преобразования типов — при делении двух переменных типа
intрезультат тоже будет целым числом, дробная часть отбрасывается. Это часто приводит к неожиданно неверным результатам.- Пример:
7 / 2даст3, а не3.5. - Как исправить: использовать преобразование типа, например,
static_cast<double>(7) / 2.
- Пример:
- Использование оператора
%с дробными числами —%работает только с целыми типами. Попытка использовать, например,5 % 2.5вызовет ошибку компиляции.- Решение: использовать функцию
fmodиз библиотеки<cmath>.
- Решение: использовать функцию
- Неправильное округление чисел — иногда люди полагаются только на формат вывода (
setprecision), думая, что число в памяти изменилось, но это не так. Для точного округления нужно использовать функцииround,ceil,floor. - Потеря данных при преобразовании типов — преобразование из
doubleвintчерезstatic_castотбрасывает дробную часть, что не то же самое, что округление. - Игнорирование беззнаковых типов (
unsigned) — неправильное использование беззнакового типа может привести к неожиданным результатам при вычитании или сравнении.
Советы по избеганию ошибок
- Всегда следи за типами переменных при арифметике.
- Используй явное преобразование типов для контроля точности.
- Для округления чисел не полагайся только на формат вывода.
- Проверяй входные данные и корректность ввода с клавиатуры.
Мини-итог: как выбирать правильный числовой тип и их использование
Правильный выбор числового типа — ключ к написанию корректного и эффективного кода.
Основные рекомендации:
- Целые числа (
int,long,long long) — используются для счётчиков, индексов, количества предметов, возраста и других количественных величин без дробной части.- Выбирай размер типа в зависимости от предполагаемых максимальных значений.
- Для значений, которые не могут быть отрицательными, рассмотри вариант
unsigned— он расширит положительный диапазон.
- Вещественные числа (
float,double) — применяются для измерений, валюты с копейками, научных вычислений, где есть дробная часть.floatподходит для ограниченной точности и экономии памяти.doubleлучше для задач с высокой точностью.
- Используй явное преобразование типов если смешиваешь разные числовые типы, чтобы избежать потери данных и неожиданных результатов.
- Округление чисел важно делать явно, если результат будет дальше использоваться в вычислениях.
- При вводе/выводе чисел следи за типом переменной и корректностью ввода, чтобы избежать ошибок.
Почему это важно?
- Неправильный тип приводит к ошибкам вычислений.
- Эффективное использование памяти.
- Понимание поведения программы и предсказуемые результаты.
Итоговый блок практических задач
17. Калькулятор потерь товара
Напишите программу, которая принимает с клавиатуры количество товаров (целое) и процент потерь (вещественное число с точностью до двух знаков после запятой). Вычислить и вывести целое число остатка товара после потерь, округленное вниз (floor).
18. Среднее арифметическое с проверкой типа
Программа запрашивает у пользователя три целых числа, вычисляет их среднее арифметическое какdouble. Необходимо обеспечить правильное преобразование типов, чтобы дробная часть не терялась. Вывести результат с точностью до 3 знаков после запятой.
19. Округление с масштабированием
Напишите функцию, которая принимает вещественное число и количество знаков после запятой (целое число), а возвращает число, округленное до этого количества знаков с помощью функцииround. Продемонстрируйте работу функции на нескольких примерах.
20. Остаток от деления дробных чисел
Реализуйте программу, которая получает два дробных числа с клавиатуры и выводит остаток их деления с помощью функцииfmod.
21. Конвертер температур
Программа получает температуру в Цельсиях (ввод с клавиатуры типомdouble) и выводит температуру в Фаренгейтах с округлением до 2 знаков после запятой. Формула: F=.
22. Вычисление процентов
Введите сумму вклада (целое) и процент годовой ставки (вещественное). Напишите программу, которая рассчитает и выведет величину процента и итоговую сумму вклада через год с точностью две цифры.
23. Вычисление площади круга
Программа должна запрашивать радиус круга какdoubleи вычислять площадь с использованием числа π из библиотеки<cmath>(M_PIили3.14159). Результат вывести с тремя знаками после запятой.
