С++/C и математика без соплей код
С++/C и математика без соплей код

Полная версия

С++/C и математика без соплей код

Язык: Русский
Год издания: 2026
Добавлена:
Настройки чтения
Размер шрифта
Высота строк
Поля

Алексей Примак

С++/C и математика без соплей код

C++ и математика без соплей

Все математические функции C++ и C: от классики до C++23, с примерами, шутками и задачами

Table of Contents

Предисловие: какого хрена мы тут собрались

Эта книга научит тебя всем математическим функциям стандартного C++ — от банального abs до гамма-функции, — и в конце каждой главы будут задачи, от которых не отвертишься.

Я буду шутить, иногда материться и разжёвывать так, чтобы дошло даже в четыре утра. Математика в программировании — это не страшно. Страшно, когда ты сравниваешь два double через == и потом три дня ищешь баг.

Что нужно

• Компилятор с поддержкой C++20: g++ 10+, clang 12+ или MSVC 2019+.

• Голова. Желательно своя.

• Терпение на задачи. Ответы в конце, но подглядывать — это как читать последнюю страницу детектива: можно, но ты лох.

Шаблон каждой программы

Почти все функции живут в заголовке . Целочисленные штуки — в , константы — в , рандом — в .



Компилируем:



Флаги -Wall -Wextra — это твоя бесплатная бабушка, которая ворчит на каждую подозрительную строчку. Слушай бабушку.

Если ты пишешь на C

Почти все функции из этой книги есть и в чистом C: они живут в . В конце каждой главы есть раздел «На чистом C», где показано, чем C отличается и что там приходится писать руками.



Флаг -lm подключает математическую библиотеку. Забудешь его — получишь ошибку линковки undefined reference to sqrt и полчаса недоумения. Флаг -std=c2x включает свежий стандарт C23 (в новых компиляторах можно писать -std=c23).

Что такое «современный C++»

Каждая глава заканчивается разделом «Современный C++»: там то же самое, но с фишками C++20 и C++23 — std::format, std::print, ranges, концепты, constexpr. Так сейчас пишут в нормальных командах. Для C++23 компилируй с флагом -std=c++23 (g++ 14+ или clang 18+).

Три правила, которые спасут тебе жопу

Всегда пиши std:: перед функцией. Без него abs(-2.5) может вызвать целочисленную версию из C и вернуть 2. Охренеть, да? Вот поэтому.

Тригонометрия работает в радианах, а не в градусах. Запомни это раз и навсегда.

double — это приближение. 0.1 + 0.2 != 0.3, и это не баг, это физика двоичных дробей.

Глава 1. Арифметика, или где тебя наебёт компьютер

Главный вывод главы: 5 / 2 в C++ равно 2, а остаток от деления отрицательного числа бывает отрицательным. Сейчас разберём почему.

1.1. Модуль: abs и fabs

Модуль — это «расстояние до нуля». Минус выкидывается, как бывший из жизни.



Подвох: std::abs(INT_MIN) — неопределённое поведение. У int минимум −2147483648, а максимум 2147483647. Положительной пары у минимума просто нет, и программа может сделать что угодно, хоть стихи напечатать.

1.2. Деление: целое против дробного

Если оба операнда целые — дробная часть отрезается нахрен. Не округляется, а именно отрезается к нулю.



Классическая ошибка новичка: double avg = sum / count;, где обе переменные int. Деление уже целое, а в double кладётся огрызок. Лечится приведением хотя бы одного операнда.

1.3. Остаток: %, fmod, remainder

Оператор % работает только с целыми. Знак результата совпадает со знаком делимого.



Для дробных чисел — std::fmod (знак как у делимого) и std::remainder (ближайшее к нулю, может быть отрицательным):



Хочешь «математический» остаток, всегда от 0 до m−1? Пиши так:



Это пригодится для дней недели, кругового буфера и всего, что крутится по кругу.

1.4. Переполнение

int не резиновый. Сложи два больших — получишь отрицательное число, а для знаковых типов это вообще неопределённое поведение.



Правило: если результат может быть большим — считай в long long с самого начала, а не после.

1.5. Современный C++: честные сравнения и проверка диапазона

Сравнение знакового и беззнакового числа — мина под ногами. Перед сравнением -1 молча превращается в 4294967295, и -1 < 1u оказывается ложью. C++20 даёт функции, которые сравнивают по-человечески:



Правило: если в сравнении встретились int и unsigned (например, i < v.size()), либо приводи типы явно, либо используй std::cmp_less.

1.6. На чистом C

В C нет std:: и нет перегрузки функций. Поэтому у модуля четыре разных имени: abs для int, labs для long, llabs для long long (все три в ) и fabs для double (в ). Перепутаешь — компилятор молча обрежет дробь.

Зато в C23 появился заголовок с проверкой переполнения (нужен gcc 14+ или clang 18+). Функция возвращает true, если результат не влез:



Задачи к главе 1

Напиши программу, которая читает два целых числа и выводит их среднее арифметическое как дробное. Проверь на 3 и 4 — должно быть 3.5, а не 3.

Дано количество секунд (например, 100000). Выведи его в формате дни:часы:минуты:секунды, используя только / и %.

Сегодня среда (день 2, если понедельник — 0). Какой день недели будет через n дней и был n дней назад? Используй функцию mod из раздела 1.3, проверь на n = 100.

Почему std::abs(-2.7) без #include может вернуть 2? Объясни своими словами и проверь на своём компиляторе.

Посчитай сумму чисел от 1 до 100000 в int и в long long. Сравни результаты и объясни разницу.

Глава 2. Степени и корни: pow, sqrt, cbrt, hypot

Главный вывод: pow — универсальный, но медленный и капризный; для квадрата пиши x * x, для корня — sqrt, для длины вектора — hypot.

2.1. pow — возведение в степень

В C++ нет оператора ^ для степени. 2 ^ 3 — это побитовое XOR, и оно равно 1. Сколько людей на этом погорело — не сосчитать.



Подвох номер два: pow возвращает double. (int)std::pow(10, 2) на некоторых старых компиляторах давал 99, потому что получалось 99.9999999. Для целых степеней пиши свою функцию:



Это называется быстрое возведение в степень. Выучи его — на собеседованиях спрашивают постоянно.

2.2. sqrt и cbrt — корни



Запомни: cbrt спокойно жрёт отрицательные числа, а pow(x, 1.0/3) — нет. Для кубического корня всегда cbrt.

Проверка «является ли число полным квадратом» — тоже ловушка из-за погрешности:



2.3. hypot — гипотенуза без переполнения

Теорема Пифагора в одну функцию:




Почему не sqrt(a*a + b*b)? Потому что при a = 1e200 квадрат улетает в бесконечность, а hypot считает аккуратно. Плюс читается красивее.

Пример: расстояние между двумя точками



2.4. Современный C++: степень на этапе компиляции

Функцию ipow можно сделать constexpr — тогда компилятор посчитает её ещё до запуска программы. А концепт std::integral не даст сунуть туда double:



static_assert — это тест, который выполняется при компиляции. Сломал функцию — программа даже не соберётся. В C++26 обещают сделать constexpr и большую часть , включая sqrt и pow.

2.5. На чистом C

Без перегрузки у каждой функции три версии: sqrtf для float, sqrt для double, sqrtl для long double. Чтобы не помнить суффиксы, есть — «перегрузка для бедных»: макросы сами выбирают нужную версию по типу аргумента.



Задачи к главе 2

Выведи 2 ^ 3 и std::pow(2, 3). Объясни, почему результаты разные.

Реализуй ipow и посчитай 2 в 62-й степени. Сравни с std::pow(2.0, 62) — совпадает ли до последней цифры?

Решение квадратного уравнения: по a, b, c выведи корни через дискриминант. Обработай три случая: два корня, один, ни одного.

Даны три точки на плоскости. Найди периметр треугольника с помощью hypot.

Выведи все полные квадраты от 1 до 1000 с помощью функции isSquare. Сколько их?

Глава 3. Логарифмы и экспонента: log, exp и их родня

Главный вывод: логарифм отвечает на вопрос «в какую степень возвести основание, чтобы получить число», а log в C++ — это натуральный логарифм, а не десятичный.

3.1. Что такое логарифм на пальцах

Если 2 в 10-й = 1024, то логарифм 1024 по основанию 2 равен 10. Всё. Логарифм — это «сколько раз надо умножить», вывернутое наизнанку.


На практике логарифм считает «сколько шагов». Сколько раз можно поделить 1000000 пополам? log2(1000000) ≈ 20. Вот почему бинарный поиск такой быстрый.

Конец ознакомительного фрагмента.

Текст предоставлен ООО «Литрес».

Прочитайте эту книгу целиком, купив полную легальную версию на Литрес.

Безопасно оплатить книгу можно банковской картой Visa, MasterCard, Maestro, со счета мобильного телефона, с платежного терминала, в салоне МТС или Связной, через PayPal, WebMoney, Яндекс.Деньги, QIWI Кошелек, бонусными картами или другим удобным Вам способом.

Конец ознакомительного фрагмента
Купить и скачать всю книгу