Функция double hypot(double x, double y)
вычисляет длину гипотенузы прямоугольного треугольника со сторонами x
и y
или расстояние от точки (x
, y
) до начала координат. Использование этой функции вместо прямой формулы sqrt(x * x + y * y)
целесообразно, поскольку ошибка намного меньше. Действительно, для некоторых значений аргумента возведение в квадрат может привести к потере точности (если значение слишком мало, возведение в квадрат дает 0), или бесконечный результат значения слишком велик. Использование прямой формулы может привести к неверным результатам, даже в пределах ожидаемого диапазона: max(|x|, |y|) <= hypot(x, y) <= sqrt(2) * max(|x|, |y|)
.
hypot()
использует альтернативные формулы, чтобы избежать этих патологических случаев, с некоторыми затратами на производительность, но если вы знаете, что ваши аргументы не вызывая потери точности или бесконечного результата, и вам нужна дополнительная скорость за счет корректности, вы можете использовать простую формулу sqrt(x * x + y * y)
.
Как правило, если x
и y
равны нулю или имеют абсолютное значение от 1e-100 до 1e + 100 и 1e-4 <= |x|/|y| <= 1e4
, sqrt
должно быть в порядке.
В вашем примере b
очень мало по сравнению с a
, что приводит к полной потере точности, поскольку b*b
на настолько меньше, чем a*a
, что a*a + b*b
невозможно отличить от a*a
. Использование long double
для промежуточного результата дает вам достаточную дополнительную точность для a*a + b*b
, чтобы быть представленным с достаточной точностью для sqrt
для вычисления значимого результата. Но поскольку sqrt(1 + epsilon)
приблизительно равно 1 + epsilon/2
, результат в любом случае пригоден для использования.