Плавающая точка в .NET - часть 1: принципы и форматы - Введение

ОГЛАВЛЕНИЕ


Введение

А вы можете сказать, что будет выведено после выполнения следующих строк? Мы подсчитываем деление на 103 в обоих случаях с одинарной и двойной точностью. Затем мы умножаем опять на 103, и сравним результаты с начальным значением:

Console.WriteLine("((double)(1/103.0))*103 < 1 is {0}.", ((double)(1/103.0))*103 < 1); Console.WriteLine("((float)(1/103.0F))*103 > 1 is {0}.", ((float)(1/103.0F))*103 > 1);

В точной арифметике, левые стороны сравнения равны 1, и потому ответ будет false (ложь) в обоих случаях. Но в обоих случаях будет выведено true (истина). Но это не все - мы получим результаты, которые не соответствуют тому, что мы ожидали с математической точки зрения. Два альтернативных способа выполнения этого подсчета дают противоречивые результаты!

Пример типичен для странной логики арифметических операций с плавающей точкой, которые не обладают лучшей репутацией. Вы встретите такое поведение во многих ситуациях. Без должной обработки ваши результаты будут неожиданными, а может даже нежеланными. К примеру, допустим, цена будет установлена в $4.99. И вы хотите узнать цену 17 единиц. Вы можете подсчитать так:

float price = 4.99F;
int quantity = 17;
float total = price * quantity;
Console.WriteLine("Общая цена равна ${0}.", total);

Вы будете ожидать результата в виде $84.83, но вы получите $84.82999. Если вы не будете осторожны, то вам это будет стоить денег. Допустим вы продаете товар за $100, и при этом предоставляете 10% скидку. Все ваши цены исчисляются целыми числами, и потому вы используете переменные типа int для хранения количества. Вот что вы получите:

int fullPrice = 100;
float discount = 0.1F;
Int32 finalPrice = (int)(fullPrice * (1-discount));
Console.WriteLine("The discounted price is ${0}.", finalPrice);

А теперь представьте, что финальная цена будет $89, а не $90 как ожидалось. Ваши клиенты будут рады, вы даете им еще 1%-ую скидку.

Существует множество примеров такого поведения. Математические равенства не всегда хорошо обрабатываются. Подсчеты не соответствуют тому, что мы учим в третьем классе - все это непонятно и запутывает. Тем не менее, мы вас уверяем, что за всем стоят четкие и точные математические операции. Цель данной статьи заключается в раскрытии этой математики для того, чтобы вы смогли умножать, добавлять и разделять с полной уверенностью.