Search code examples
javascriptfloating-pointieee-754math-functions

Is Math.sqrt(x) and Math.pow(x, 0.5) equivalent?


In ECMAScript, given a non-negative, finite double x, is the following assertion always true?

Math.sqrt(x) === Math.pow(x, 0.5)

I know that both Math.sqrt() and Math.pow() are implementation-approximated, and the result may vary across platforms. However, are they truly interchangeable, or are there cases where this assertion evaluates to false?

I wrote a simple test program to check for counterexamples, but couldn't find any:

let x;
while (true) {
    x = Math.random();
    if (!Object.is(Math.sqrt(x), Math.pow(x, 0.5))) {
        break;
    }
}

I also found this question, where the assertion fails in Python. However, when testing the same example in JavaScript, I couldn't reproduce the error.

Can this assertion ever be false? Or is it guaranteed to be always true?


Solution

  • I know that both Math.sqrt() and Math.pow() are implementation-approximated, and the result may vary across platforms. However, are they truly interchangeable, or are there cases where this assertion evaluates to false?

    Since you know the results of Math.sqrt(x) and Math.pow(x, 0.5) are not fully specified and the results of either one of them can vary between ECMAScript implementations, the only question remaining is whether the results of the two of them can differ in a single ECMAScript implementation. Scanning discussion of “implementation-approximated” in ECMAScript 2024 Language Specification does not show any constraints that require them to be equal.

    It is not even clear that the language specification requires the approximations to produce the same value every time. That lack would allow Math.sqrt(1) === Math.sqrt(1) to evaluate as false.

    Additionally, if x is a NaN or is negative, we expect the results of each operation to be a NaN, in which case the === operator evaluates as false.