Как позволить -1 == — 1.0000000000001

Вот часть моего кода:

double tmp = OP.innerProduct(OQ);
double tmp2 = -1;

и значение tmp а также tmp2 это: (в двоичном виде)

tmp = 0b1011111111110000000000000000000000000000000000000000000000000001
tmp2= 0b1011111111110000000000000000000000000000000000000000000000000000

Если бы я использовал acos(tmp), он вернется nan,

Я не хочу nan значение, и я хотел бы игнорировать небольшую ошибку, чтобы сохранить tmp в диапазоне [-1,1].

Как это сделать?

РЕДАКТИРОВАТЬ:

У меня есть две точки в сферической координате. (например, (r, 45,45) (r, 225, -45))

Затем мне нужно изменить их на декартову координату. (небольшая ошибка происходит здесь!)

Затем я хочу вычислить угол между двумя точками.

Аналитическое решение отличается от компьютерного решения (так как небольшая ошибка).
Я хотел бы сделать два решения одинаковыми.

1

Решение

Вы пытаетесь предотвратить ветвление? Обычно я делаю маленького помощника, когда делаю что-то вроде этого:

template<typename T>
inline T Clamp( T val, T low, T high ) {
return val < low ? low : (val > high ? high : val);
}

А потом:

double result = acos( Clamp(tmp, -1.0, 1.0) );

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

[править] Я только что поиграл с зажимом [-1,1] без разветвления. Конечно, это только лечит неточности. Если вы позвоните по номеру, который находится за пределами диапазона, он будет бомбить:

inline double safer_acos (double val)
{
double vals[] = {-1.0, val, val, 1.0};
return acos( vals[int(2.0 + val)] );
}
2

Другие решения

Других решений пока нет …