Тема не новая, просто еще раз с ней столкнулся, в одном неожиданном для меня месте. Так что, если вы работаете со значениями с плавающей точкой, будьте готовы к вот такому, с первого взгляда не понятному явлению.
Это скриншот из панели WatchList VisualStudio 2010, получается, что 1.6+0.4 не равно 2, если используется тип float. Попробую объяснить.
Где ждать проблему?
Первый раз с такой проблемой я столкнулся, когда писал игры на Flash (парадоксально, то что сейчас тоже писал игру 🙂 ). Рассчитывалось движение монетки в игре Pajazzo. Так как сервер сам выбирал куда попадет монетка, нужно было создать карту «сила заброса-заработок» и после этого выбирать один из подходящих путей. При переходе с Flash 8 на Flash 9, движение монеток стало другим и рассчитанный путь не работал в новой версии. Дело оказалось именно в способе округления чисел с плавающей точкой. Решение было неоднозначным, я округлял числа сам примерно таким образом: (int(x*100)+int(offsetX*100))/100. Таким образом я округлял число до двух чисел после запятой.
В C# схожая ситуация, но тут есть специальный метод. Из
if (x + iterator.X <= size.X && y + iterator.Y <= size.Y) { }
получаем:
if (Math.Round(x + iterator.X, 1) <= Math.Round(size.X,1) && Math.Round(y + iterator.Y,1) <= Math.Round(size.Y,1)) { }
Как показывает пример на скриншоте, проблема есть только у типа float. Тип double по всей видимости хранится по другому.
Почему же 1.6+0.4!=2.0?
Еще на лекциях по информатике, мы на бумаге преобразовывали десятеричные числа в двуричные. С целыми числами тут все в порядке:
1b=1, 10b=2, 11b=3 и т.д. А вот вещественные числа могут хранить только примерное значение, так: 0.1b=0,5, 0,01b=0,25, 0,11b=0,75 и т.д. Чтобы хранить числа «правильно» (как думаю, double в C#) введена мантисса — это значение говорит, где поставить запятую и разделить его дробную часть от целой. Таким образом, числа хранятся как целые, а потом доставляется запятая в нужном месте.
Метки:C#, Flash, разработка
Похожие статьи
- 12 января 2012 -- Генерация строк перебором букв. (4)
- 18 февраля 2010 -- Рекурсивно удаляем PYC файлы. (3)
- 4 февраля 2009 -- LINQ Insert or Update еще одно решение. (2)
- 29 апреля 2010 -- Джобс не останавливается опускать Flash (7)
- 7 июля 2008 -- Играем MP3 при загрузке страницы. (1)