cpp

Числа

В языке C++ практически все элементарные типы данных (bool, char, wchar_t, int, short, long, long long, float, double и long double) являются числовыми. Тип bool может принимать только значения 1 и 0, которые соответствуют константам true и false. Типы char и wchar_t содержат код символа, а не сам символ. Поэтому значения этих типов можно использовать в одном выражении вместе со значениями, имеющими числовые типы. Пример:

bool a = true; // 1
char ch = 'w'; // 119
std::cout << (a + ch + 10) << std::endl; // 130

Для хранения целых чисел предназначен тип int. Диапазон значений зависит от компилятора. Минимальный диапазон от –32 768 до 32 767. На практике диапазон от –2 147 483 648 до 2 147 483 647 (занимает 4 байта).

С помощью ключевых слов short, long и long long можно указать точный размер типа int. При использовании этих ключевых слов тип int подразумевается по умолчанию, поэтому его можно не указывать. Тип short занимает 2 байта (диапазон от –32 768 до 32 767), тип long — 4 байта (диапазон от –2 147 483 648 до 2 147 483 647), а тип long long занимает 8 байт (диапазон значений от –9 223 372 036 854 775 808 до 9 223 372 036 854 775 807).

По умолчанию целочисленные типы являются знаковыми (signed). Знак числа хранится в старшем бите: 0 соответствует положительному числу, а 1 — отрицательному. С помощью ключевого слова unsigned можно указать, что число является только положительным. Тип unsigned char может содержать числа в диапазоне от 0 до 255, тип unsigned short — от 0 до 65 535, тип unsigned long — от 0 до 4 294 967 295, а тип unsigned long long — от 0 до 18 446 744 073 709 551 615.

При преобразовании значения из типа signed в тип unsigned следует учитывать, что знаковый бит (если число отрицательное, то бит содержит значение 1) может станет причиной очень больших чисел, так как старший бит у типа unsigned не содержит признака знака:

int x = -1;
std::cout << (unsigned int)x << std::endl; // 4294967295

Целочисленное значение задается в десятичной, восьмеричной или шестнадцатеричной форме. Восьмеричные числа начинаются с нуля и содержат цифры от 0 до 7. Шестнадцатеричные числа начинаются с комбинации символов 0x (или 0X) и могут содержать числа от 0 до 9 и буквы от A до F (регистр букв не имеет значения). Восьмеричные и шестнадцатеричные значения преобразуются в десятичное значение. Пример:

int x, y, z;
x = 119;                     // Десятичное значение
y = 0167;                    // Восьмеричное значение
z = 0xFF;                    // Шестнадцатеричное значение
std::cout << x << std::endl; // 119
std::cout << y << std::endl; // 119
std::cout << z << std::endl; // 255
std::printf("%#o\n", y);     // 0167
std::printf("%#X\n", z);     // 0XFF

Присвоить переменной нулевое значение можно указав круглые скобки после названия типа или пустые фигурные скобки после переменной при объявлении:

int x = int(); // x равно 0
int y {};      // y равно 0
std::cout << x << std::endl; // 0
std::cout << y << std::endl; // 0

Начиная со стандарта C++14, в составе числового литерала можно использовать одинарную кавычку:

int x = 1'000'000'000;
std::cout << x << std::endl; // 1000000000

Согласитесь, что так нагляднее виден порядок числа. Одинарную кавычку можно использовать не только для типа int, но и для других числовых типов.

После целочисленной константы могут быть указаны следующие суффиксы:

  • без суффикса — в зависимости от значения может иметь тип int, long или long long (компилятор выбирает минимальный тип из указанных, позволяющий хранить значение):
std::cout << sizeof(1) << std::endl;                   // 4
std::cout << sizeof(2147483647) << std::endl;          // 4
std::cout << sizeof(2147483648) << std::endl;          // 8
std::cout << sizeof(9223372036854775807) << std::endl; // 8
// warning: integer constant is so large that it is unsigned
// std::cout << sizeof(9223372036854775808) << std::endl;
  • L (или l) — в зависимости от значения может иметь тип long или long long (компилятор выбирает минимальный тип из указанных, позволяющий хранить значение). Пример указания значения: 10L;
  • LL (или ll) — тип long long. Пример указания значения: 10LL;
  • U (или u) — в зависимости от значения может иметь тип unsigned int, unsigned long или unsigned long long (компилятор выбирает минимальный тип из указанных, позволяющий хранить значение). Пример указания значения: 10U;
  • UL — в зависимости от значения может иметь тип unsigned long или unsigned long long. Пример указания значения: 10UL;
  • ULL — тип unsigned long long. Пример указания значения: 10ULL.

Пример объявления переменных с указанием суффиксов:

int i = 10;
unsigned int ui = 4294967295U;
std::printf("%d\n", i);  // 10
std::printf("%u\n", ui); // 4294967295
std::cout << sizeof(10) << std::endl;           // 4
std::cout << sizeof(4294967295U) << std::endl;  // 4
std::cout << sizeof(4294967295) << std::endl;   // 8
long l = 2147483647L;
unsigned long ul = 4294967295UL;
std::printf("%ld\n", l);  // 2147483647
std::printf("%lu\n", ul); // 4294967295
std::cout << sizeof(2147483647L) << std::endl;  // 4
std::cout << sizeof(4294967295UL) << std::endl; // 4
std::cout << sizeof(4294967295L) << std::endl;  // 8
long long ll = 9223372036854775807LL;
unsigned long long ull = 18446744073709551615ULL;
std::printf("%lld\n", ll);   // 9223372036854775807
std::printf("%llu\n", ull);  // 18446744073709551615

Для хранения вещественных чисел предназначены типы float, double и long double. Вещественное число может содержать точку и (или) экспоненту, начинающуюся с буквы E (регистр не имеет значения):

float x, y;
double z, k;
x = 20.0F;
y = 12.1e5F;
z = .123;
k = 47.E-5;
std::printf("%.5f\n", x);              // 20.00000
std::printf("%e\n", y);                // 1.210000e+06
std::printf("%.2f\n", z);              // 0.12
std::printf("%g\n", k);                // 0.00047
std::cout << x << std::endl;           // 20
std::cout << y << std::endl;           // 1.21e+06
std::cout << z << std::endl;           // 0.123
std::cout << k << std::endl;           // 0.00047

Присвоить переменной нулевое значение можно указав круглые скобки после названия типа или пустые фигурные скобки после переменной при объявлении:

float x = float();
double y = double();
float z {};
double k {};
std::cout << x << std::endl;           // 0
std::cout << y << std::endl;           // 0
std::cout << z << std::endl;           // 0
std::cout << k << std::endl;           // 0

По умолчанию вещественные константы имеют тип double. Если необходимо изменить тип на другой, то после числа указываются следующие суффиксы:

  • F (или f) — тип float. Пример указания значения: 12.3f;
  • L (или l) — тип long double. Значение должно содержать точку и (или) экспоненту, иначе тип будет long int. Пример указания значения: 12.3L.

Пример указания суффиксов:

std::cout << sizeof(20.0F) << std::endl; // 4
std::cout << sizeof(20.0) << std::endl;  // 8
std::cout << sizeof(20.0L) << std::endl; // 16

При выполнении операций над вещественными числами следует учитывать ограничения точности вычислений. Например, результат следующей инструкции может показаться странным:

std::cout << (0.3 - 0.1 - 0.1 - 0.1) << std::endl; // -2.77556e-17

Ожидаемым был бы результат 0.0, но как видно из примера мы получили совсем другой результат (-2.77556e-17).

Если в выражении используются числа, имеющие разный тип данных, то тип результата выражения будет соответствовать наиболее сложному типу. Например, если производится сложение переменной, имеющей тип int, с переменной имеющей тип double, то целое число будет автоматически преобразовано в вещественное. Результатом этого выражения будет значение, имеющее тип double. Однако, если результат выражения присваивается переменной типа int, то тип double будет преобразован в тип int (при этом компилятор выведет предупреждающее сообщение о возможной потере данных):

int x = 10, y = 0;
double z = 12.5;
y = x + z;
// warning: conversion from 'double' to 'int' may change value
std::cout << y << std::endl;       // 22 (тип int)
std::cout << (x + z) << std::endl; // 22.5 (тип double)

Чтобы компилятор не выводил предупреждающего сообщения, следует выполнить приведение типов:

y = static_cast<int>(x + z);

Математические константы

В заголовочном файле math.h определены следующие макросы, содержащие значения математических констант:

  • M_PI — число ПИ. Определение макроса:
#define M_PI       3.14159265358979323846
  • M_PI_2 — значение выражения pi/2. Определение макроса:
#define M_PI_2     1.57079632679489661923
  • M_PI_4 — значение выражения pi/4. Определение макроса:
#define M_PI_4     0.78539816339744830962
  • M_1_PI — значение выражения 1/pi. Определение макроса:
#define M_1_PI     0.31830988618379067154
  • M_2_PI — значение выражения 2/pi. Определение макроса:
#define M_2_PI     0.63661977236758134308
  • M_E — значение константы e. Определение макроса:
#define M_E        2.7182818284590452354
  • M_LOG2E — значение выражения log2(e). Определение макроса:
#define M_LOG2E    1.4426950408889634074
  • M_LOG10E — значение выражения log10(e). Определение макроса:
#define M_LOG10E   0.43429448190325182765
  • M_LN2 — значение выражения ln(2). Определение макроса:
#define M_LN2      0.69314718055994530942
  • M_LN10 — значение выражения ln(10). Определение макроса:
#define M_LN10     2.30258509299404568402
  • M_2_SQRTPI — значение выражения 2/sqrt(pi). Определение макроса:
#define M_2_SQRTPI 1.12837916709551257390
  • M_SQRT2 — значение выражения sqrt(2). Определение макроса:
#define M_SQRT2    1.41421356237309504880
  • M_SQRT1_2 — значение выражения 1/sqrt(2). Определение макроса:
#define M_SQRT1_2  0.70710678118654752440

Прежде чем использовать константы необходимо перед подключением файла math.h определить макрос с названием _USE_MATH_DEFINES. В VC++ без этого макроса константы недоступны. В MinGW определять макрос не нужно. Пример вывода значения констант приведен в листинге 5.1.

Листинг 5.1. Вывод значений математических констант

#include <iostream>
#define _USE_MATH_DEFINES
#include <math.h>

int main() {
   std::cout << M_PI << std::endl; // 3.14159
   std::cout << M_E << std::endl;  // 2.71828
   return 0;
}

Учебник C++ (Qt Creator и MinGW)
Учебник C++ (Qt Creator и MinGW) в формате PDF

Реквизиты

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов

cpp