У меня есть проблема с отменой в арифметике с плавающей точкой. Я знаю, в чем проблема, но я не могу придумать эффективного решения.
Вот моя проблема: у меня есть симуляция частиц в 3D, поэтому у каждой частицы есть 3 координаты (x, y, z). Весь домен разбит на подэлементы. В какой-то момент я вычисляю идентификатор подэлемента, в котором частица находится на временном шаге. Это простая формула:
int cellOffset_y = (pos[1] - y_min) / cellWidth_y;
pos [1] — x-координата частицы, y_min — начало домена, а cellWidth — ширина ячейки.
Вот моя проблема: у меня есть контрольный пример, в котором координаты частицы должны быть 0. Из-за неточности с плавающей запятой, это прибл. -3E-18. Когда я использую эту формулу, -3e-18 падает из-за отмены. Большая проблема здесь заключается в том, что, поскольку положение частицы отрицательное, а граница точно равна 0, я получаю другой идентификатор cellID, чем та, в которой действительно находится частица.
Так у кого-нибудь есть идеи, как решить эту проблему? Я надеюсь, что это четко указано
Есть в основном два варианта (ну, три, если вы считаете «жить с проблемой» как правильный выбор!):
Сдвиньте границы в вашей сетке на небольшое количество, чтобы учесть некоторый уровень неточности вверх по течению. Таким образом, расчет станет (pos - y_min + k) / width
для некоторого небольшого значения k
,
Конечно, это не справляется с ошибками, которые происходят в другом направлении (то есть, числа, которые немного слишком велики); на самом деле, это усугубляет ситуацию. Но нет общего способа решить эту проблему; ваш код не может «знать», является ли -3e-18 правильным или просто немного неправильным!
Исправьте подсчет вверх по течению.
Других решений пока нет …