Шрифт:
Интервал:
Закладка:
Рассмотрим целочисленную задачу.
short int y = 40000;
int i = 1000000;
cout << y << " " << i*i << "n";
Выполнив эту программу, получим следующий результат:
–25536 –727379968
Этого следовало ожидать. Здесь мы видим эффект переполнения. Целочисленные типы позволяют представить лишь относительно небольшие целые числа. Нам просто не хватит битов, чтобы точно представить каждое целое число, поэтому нам необходим способ, позволяющий выполнять эффективные вычисления. В данном случае двухбайтовое число типа short не может представить число 40 000, а четырехбайтовое число типа int не может представить число 1 000 000 000 000. Точные размеры встроенных типов в языке C++ (см. раздел A.8) зависят от аппаратного обеспечения и компилятора; размер переменной x или типа x в байтах можно определить с помощью оператора sizeof(x). По определению sizeof(char)==1. Это можно проиллюстрировать следующим образом.


Целое число можно присвоить переменной, имеющей тип числа с плавающей точкой. Если целое число окажется больше, чем может представить тип числа с плавающей точкой, произойдет потеря точности. Рассмотрим пример.
cout << "размеры: " << sizeof(int) << ' ' << sizeof(float) << 'n';
int x = 2100000009; // большое целое число
float f = x;
cout << x << ' ' << f << endl;
cout << setprecision(15) << x << ' ' << f << 'n';
На нашем компьютере мы получили следующий результат:
Sizes: 4 4
2100000009 2.1e+009
2100000009 2100000000
Типы float и int занимают одинаковое количество памяти (4 байта). Тип float состоит из мантиссы (как правило, числа от нуля до единицы) и показателя степени (т.е. мантисса*10 показатель степени), поэтому он не может точно выразить самое большое число int. (Если бы мы попытались сделать это, то не смогли бы выделить достаточно памяти для мантиссы после размещения в памяти показателя степени.) Как и следовало ожидать, переменная f представляет число 2100000009 настолько точно, насколько это возможно. Однако последняя цифра 9 вносит слишком большую ошибку, — именно поэтому мы выбрали это число для иллюстрации.

float f = 2.8;
int x = f;
cout << x << ' ' << f << 'n';
Значение переменной x будет равно 2. Оно не будет равным 3, как вы могли подумать, если применили “правило округления 4/5”. В языке C++ преобразование типа float в тип int сопровождается усечением, а не округлением.

Язык C++ не решит эту проблему за вас. Рассмотрим пример.
void f(int i, double fpd)
{
char c = i; // да: тип char действительно представляет
// очень маленькие целые числа
short s = i; // опасно: переменная типа int может
// не поместиться
// в памяти, выделенной для переменной
// типа short
i = i+1; // что, если число i станет максимальным?
long lg = i*i; // опасно: переменная типа long не может
// вместить результат
float fps = fpd; // опасно: большее число типа large может
// не поместиться в типе float
i = fpd; // усечение: например, 5.7 –> 5
fps = i; // можно потерять точность (при очень
// больших целых)
}
void g()
{
char ch = 0;
for (int i = 0; i<500; ++i)
cout << int(ch++) << 't';
}
Если сомневаетесь, поэкспериментируйте! Не следует отчаиваться и в то же время нельзя просто читать документацию. Без экспериментирования вы можете не понять содержание весьма сложной документации, связанной с числовыми типами.
ПОПРОБУЙТЕ
Выполните функцию g(). Модифицируйте функцию f() так, чтобы она выводила на печать переменные c, s, i и т.д. Протестируйте программу на разных значениях.

24.2.1. Пределы числовых диапазонов
