Проблема двойной точности C #, как обнаружить и обработать безопасным способом - PullRequest
3 голосов
/ 03 ноября 2011

Я искал удовлетворительное и безопасное решение моей проблемы двойной точности, указанной для этой проблемы:

enter image description here

Эта программа пытается определить, сколько маленьких кружков может поместиться в большой кружок. Он заполняет большой круг, а затем отбирает те, которые пересекают большую окружность. используя эту формулу:

distance_small_pos_from_center + small_radius < big_radius

Все вычисления были в двойном, за исключением вывода экрана на WinForms, который принимает int для координат.

enter image description here

На изображении выше показан результат выбраковки. Вы можете видеть, что это не симметрично, когда это действительно должно быть, потому что ограничение состоит в том, что должен быть один маленький круг точно в центре. Я перебираю код и обнаруживаю, что это потому, что некоторые вычисления дают, например,

99.9999999 < 100

Этот ответ C ++ с двойной точностью и округлением говорит, что мы должны использовать всю доступную точность, но в этом случае мне пришлось сделать Math.Round(distance_small_pos_from_center + small_radius, 3), используя 3 произвольно.

Результат отбраковки сильно отличается без Math.Round. Оглядываясь назад, это один из видов ошибок, который трудно обнаружить , если бы я его не вытянул . Может быть, я сделал что-то не так, или не понял, удваивает столько, сколько я думал.

Итак, у кого-нибудь есть решения или советы, чтобы избежать такого рода проблем?

Ответы [ 2 ]

2 голосов
/ 03 ноября 2011

Извините, что не смог дать полный ответ на ваш вопрос, но у меня сейчас нет времени на это. Но когда вы сравниваете числа с плавающей точкой, сравните их с «допуском», поскольку число с плавающей точкой не является точным.

РЕДАКТИРОВАТЬ: модифицировано с помощью abs (), если вы не знаете, что является большим и маленьким, как указал Ханс Кестинг

Т.е., сделайте что-то вроде if(abs(big_radius - distance_small_pos_from_center) < epsilon), где epsilon - ваш допуск, выбранный с учетом того, насколько "неточными" будут поплавки в диапазоне, где вы работаете.

Для более точной информации см .:

http://www.cygnus -software.com / документы / comparingfloats / comparingfloats.htm

http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html

http://www.cplusplus.com/forum/articles/3638/

0 голосов
/ 03 ноября 2011

Использовать System.Decimal:

http://msdn.microsoft.com/en-us/library/system.decimal.aspx

...