Фокусы компьютерной арифметики
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)) верно!