It's already discussed here that hypot
is slower than sqrt
because it handles cases when the two inputs are huge or tiny so that sqrt
would wrongly return inf or 0.
However, according to some test, hypot
is even slower than first convert to higher precision and then do trivial calculation and convert back.
So, in what case should I use hypot
? Only when there's no larger float type and overflow is an issue?
EDIT: sqrtl
and hypot
differ on input a=1,b=1.8e-8
, but sqrtl
returns more accurate result:
hypot 1.0
sqrtl 1.000000000000000222044604925031
exact 1.000000000000000161999999999999986878000000000002125764000...
1+eps 1.0000000000000002220446049250313080847263336181640625
Exact lines where an eps is added to result is shown here
The function double hypot(double x, double y)
computes the length of the hypotenuse of a right triangle with sides of x
and y
, or the distance
of the point (x
, y
) from the origin. Using this function instead of the direct formula sqrt(x * x + y * y)
is wise, since the error is
much smaller. Indeed for some argument values, squaring can cause either a loss of precision (if the value is too small, squaring it produces 0), or an infinite result of the value is too large. Using the direct formula can produce incorrect results, not even inside the expected range: max(|x|, |y|) <= hypot(x, y) <= sqrt(2) * max(|x|, |y|)
.
hypot()
uses alternative formulae to avoid these pathological cases, at some performance cost, but if you know your arguments are not causing a loss of precision nor an infinite result, and you need extra speed at the expense of correctness, you can use the simple formula sqrt(x * x + y * y)
.
As a rule of thumb, if x
and y
are zero or they have an absolute value between 1e-100 and 1e+100 and 1e-4 <= |x|/|y| <= 1e4
, sqrt
should be fine.
In your example, b
is very small compared to a
, causing a complete loss of precision because b*b
is so much smaller than a*a
that a*a + b*b
cannot be distinguished from a*a
. Using the long double
for the intermediary result gains you enough extra precision for a*a + b*b
to be represented with enough precision for sqrt
to compute a meaningful result. But since sqrt(1 + epsilon)
is approximately 1 + epsilon/2
, the result is usable anyway.
This is because your are comparing things that you should not... hypot
is not converting to higher precision, computing the square root and converting back to lower precision. hypot uses a dedicated algorithm to ensure that the computation will return a good result, even if numbers are huge or tiny for a given precision. There is an hypotl
to compute the length for long doubles that you cannot compute well using sqrtl
. And, long double
may be the exact same type than double
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With