How is pow() calculated in C?

前端 未结 4 2111
慢半拍i
慢半拍i 2021-01-05 09:42

Our professor said that you can\'t calculate ab if a<0 using pow() because pow() uses natural logarithms to calculate it (ab

4条回答
  •  有刺的猬
    2021-01-05 10:07

    The second question (why does it return a domain error) is already covered in the comments, but adding for completeness: pow takes two real numbers and returns a real number. Applying a rational exponent on a negative number takes you out of the domain of real numbers into the domain of complex numbers, which the result of this function (a double) can't represent.

    If you're curious about the actual implementation, well, there are many and it depends on many factors, such as architecture and level of optimisation. It's quite difficult to find one that reads easily, but FDLIBM (Freely Distributable LIBM) has one which has at least has a good explanation in the comments:

    /* __ieee754_pow(x,y) return x**y
     *
     *            n
     * Method:  Let x =  2   * (1+f)
     *  1. Compute and return log2(x) in two pieces:
     *      log2(x) = w1 + w2,
     *     where w1 has 53-24 = 29 bit trailing zeros.
     *  2. Perform y*log2(x) = n+y' by simulating muti-precision 
     *     arithmetic, where |y'|<=0.5.
     *  3. Return x**y = 2**n*exp(y'*log2)
     *
     * Special cases:
     *  1.  (anything) ** 0  is 1
     *  2.  (anything) ** 1  is itself
     *  3.  (anything) ** NAN is NAN
     *  4.  NAN ** (anything except 0) is NAN
     *  5.  +-(|x| > 1) **  +INF is +INF
     *  6.  +-(|x| > 1) **  -INF is +0
     *  7.  +-(|x| < 1) **  +INF is +0
     *  8.  +-(|x| < 1) **  -INF is +INF
     *  9.  +-1         ** +-INF is NAN
     *  10. +0 ** (+anything except 0, NAN)               is +0
     *  11. -0 ** (+anything except 0, NAN, odd integer)  is +0
     *  12. +0 ** (-anything except 0, NAN)               is +INF
     *  13. -0 ** (-anything except 0, NAN, odd integer)  is +INF
     *  14. -0 ** (odd integer) = -( +0 ** (odd integer) )
     *  15. +INF ** (+anything except 0,NAN) is +INF
     *  16. +INF ** (-anything except 0,NAN) is +0
     *  17. -INF ** (anything)  = -0 ** (-anything)
     *  18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
     *  19. (-anything except 0 and inf) ** (non-integer) is NAN
     *
     * Accuracy:
     *  pow(x,y) returns x**y nearly rounded. In particular
     *          pow(integer,integer)
     *  always returns the correct integer provided it is 
     *  representable.
     *
     * Constants :
     * The hexadecimal values are the intended ones for the following 
     * constants. The decimal values may be used, provided that the 
     * compiler will convert from decimal to binary accurately enough 
     * to produce the hexadecimal values shown.
     */
    

    So, in short, the mechanism is as you described it and relies on calculating the logarithm first, but with many special cases that need to be accounted for.

提交回复
热议问题