在C中如何计算pow()? [英] How is pow() calculated in C?

查看:297
本文介绍了在C中如何计算pow()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们的教授说,如果a <<0,则无法使用pow()计算a b ,因为pow()使用自然对数进行计算(a b = e b ln a ),由于未定义负数,因此无法计算.我试过了,只要b是一个整数,它就可以工作.

Our professor said that you can't calculate ab if a<0 using pow() because pow() uses natural logarithms to calculate it (ab=eb ln a) and since it's undefined for negative numbers it can't be calculated. I tried it and it works as long as b is an integer.

我已经搜索了math.h和更多文件,但是无法找到该函数的定义方式以及它用于计算的内容.我也尝试过搜索互联网,但没有成功.在堆栈溢出方面也有类似的问题此处(适用于C# ). (最后一个很好,但是我找不到源代码.)

I have searched through math.h and further files, but was unable to find how the function is defined and what it uses to calculate. I also tried searching the internet, but without any success. There are similar questions on Stack Overflow right here and here (for C#). (the last one is good, but I was unable to find sourcecode.)

所以问题是pow()在C语言中是如何实际计算的?为什么当基数为负数且指数为有限且非整数时,为什么会返回域错误?

So the question is how is pow() actually calculated in C? And why does it return a domain error when the base is finite and negative and the exponent is finite and non-integral?

推荐答案

如果您好奇如何在实践中实现pow函数,可以查看源代码.在不熟悉的(大型)代码库中进行搜索以找到您要查找的部分是一种诀窍",并且可以进行一些练习.

If you're curious how the pow function might be implemented in practice, you can look at the source code. There is a kind of "knack" to searching through unfamiliar (and large) codebases to find the section you are looking for, and it's good to get some practice.

C库的一种实现是glibc,它在GitHub上具有镜像.我没有找到官方镜像,但是在 https://github.com/lattera/glibc

One implementation of the C library is glibc, which has mirrors on GitHub. I didn't find an official mirror, but an unofficial mirror is at https://github.com/lattera/glibc

我们首先查看 math/w_pow.c 文件,有一个很有前途的名字.它包含一个调用__ieee754_pow的函数__pow,我们可以在

We first look at the math/w_pow.c file which has a promising name. It contains a function __pow which calls __ieee754_pow, which we can find in sysdeps/ieee754/dbl-64/e_pow.c (remember that not all systems are IEEE-754, so it makes sense that the IEEE-754 math code is in its own directory).

它以一些特殊情况开头:

It starts with a few special cases:

if (y == 1.0) return x;
if (y == 2.0) return x*x;
if (y == -1.0) return 1.0/x;
if (y == 0) return 1.0;

再远一点,您会发现一个带有注释的分支

A little farther down you find a branch with a comment

/* if x<0 */

哪个引导我们去

return (k==1)?__ieee754_pow(-x,y):-__ieee754_pow(-x,y); /* if y even or odd */

因此您可以看到,对于负数x和整数ypow的glibc版本将计算pow(-x,y),然后如果y为奇数,则结果为负.

So you can see, for negative x and integer y, the glibc version of pow will compute pow(-x,y) and then make the result negative if y is odd.

这不是做事情的唯一方法,但是我想这对许多实现来说都是很常见的.您会看到pow充满特殊情况.这在库数学函数中很常见,应该可以在不友好的输入(如非正规和无穷大)上正常使用.

This is not the only way to do things, but my guess is that this is common to many implementations. You can see that pow is full of special cases. This is common in library math functions, which are supposed to work correctly with unfriendly inputs like denormals and infinity.

pow函数特别难以阅读,因为它是经过高度优化的代码,可以对浮点数进行位旋转.

The pow function is especially hard to read because it is heavily-optimized code which does bit-twiddling on floating-point numbers.

C标准(n1548§7.12.7.4)具有关于pow的说法:

The C standard (n1548 §7.12.7.4) has this to say about pow:

如果x是有限的并且是负数,而y是有限的而不是整数值,则会发生域错误.

A domain error occurs if x is finite and negative and y is finite and not an integer value.

因此,根据C标准,负面的x 应该起作用.

So, according to the C standard, negative x should work.

还有附录F的问题,它对pow在IEEE-754/IEC-60559系统上的工作方式给出了更严格的约束.

There is also the matter of appendix F, which gives much tighter constraints on how pow works on IEEE-754 / IEC-60559 systems.

这篇关于在C中如何计算pow()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆