У меня есть расчет с использованием double
, и я столкнулся с проблемами из-за катастрофической отмены c (вычитаются почти равные значения). Я ищу перестановку, чтобы свести потерю значимости к минимуму.
Мое уравнение - это уравнение плоскости, из которой я вычисляю z = z(x, y)
(с набором констант z0, x21, ...
):
// (z-z0)*(x21*y31 - y21*x31) = (x-x0)*(y21*z31 - z21*y31) + (y-y0)*(z21*x31-x21*z31)
double z = z0 + (x-x0)*(y21*z31 - z21*y31)/(x21*y31 - y21*x31)
+ (y-y0)*(z21*x31-x21*z31)/(x21*y31 - y21*x31);
Один набор значений, для которого я сталкиваюсь с проблемами приведен ниже. В данном случае это происходит из-за того, что все члены y близки к нулю (y21 ~= -0.0032, y31 ~= -0.0097, y-y0 ~= -0.0032
):
(z-z0) * 9.3241e-18 ~= 0.1112*0.0830 + (-0.0032)*2.8428
~= 0.009234 - 0.009234
~= 5.2042e-18
Результат едва ли можно использовать, так как я подозреваю, что на 9.3241e-18
и 5.2042e-18
влияют ошибки вычислений.
Я ищу способ справиться с ошибками вычислений из-за вычитания в целом и умной перестановки для особого случая, когда y21, y31, y-y0
близко к нулю в частности. Попытка перестановки пока не увенчалась успехом. Как я могу справиться с этими вычислительными проблемами (в C ++).