Как обойти ошибки вычислений при вычитании почти равных двойных значений? - PullRequest
1 голос
/ 28 мая 2020

У меня есть расчет с использованием 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 ++).

...