Фокусы компьютерной арифметики

Post date: Oct 5, 2010 12:47:59 PM

Компьютерную арифметику разделяют на две группы: целочисленная и вещественная. Работа с первой достаточно проста, нам рассказывают про целые и натуральные числа ещё с начальных классов школы. Единственное, что вносит компьютерная целочисленная арифметика - это понятие переполнения, когда результат арифметической операции достаточно "большой" (по модулю) и не может быть представлен в текущем формате.

С вещественной арифметикой гораздо интереснее! Вещественная арифметика представляет числа не равномерно на числовой оси, числа имеют большую плотность в окрестности нуля и меньшую в отдалении от него, кодирование вещественных чисел более сложное, нежели для целых чисел, вещественная арифметика может кодировать "бесконечности" и "не числа" (NaN – Not a Number, может возникать при операции деления на ноль). Со всеми этими особенностями большинство разработчиков не сталкиваются и работают с компьютерной вещественной арифметикой как с обычными действительными числами матанализа, но это таит в себе потенциальные ошибки. Приведу замечательный пример, с которым я столкнулся.

#include <iostream>

using namespace std;

int main()

{

float a = 0.34f;

float b = 0.35f;

int aInt = (int)(a * 100);

int bInt = (int)(b * 100);

cout << aInt << endl;

cout << bInt << endl;

}

Если вы запустите эту программу, то увидите на экране два числа: "34 34". И это не опечатка!

Дело в том, что возможности вещественной арифметики не позволяют представлять число 0.35f, поэтому вместо него в памяти хранится число 0.34999999. При выполнении приведения типа float к типу int происходит отбрасывание дробной части числа 34.999999 и получается, что выражение (int (a * 100)) == (int (b * 100)) верно!