为什么math.h有pow()返回double而不是int

时间:2015-04-01 10:52:11

标签: c

出于好奇,我知道pow()会返回double

math.h将此API与double作为参数和返回值,是否有任何特殊原因。

如果我有一个需要int作为返回值的情况,我会编写自己的API,如下所示。为什么math.h没有这样的API并且double pow(double,double);

还是有一个吗?如果答案太明显,请告诉我,我会删除这个问题。我无法弄清楚这背后的原因。

int i = pow1(2,4);

int pow1(int i,int j)
{
   int k = 1;
   while(j--)
   {
      k = k*i;
   }
   return k;
}

3 个答案:

答案 0 :(得分:3)

我会考虑以下论点:

  • C标准库已经很大了,每个额外的功能都有成本;提供单个pow函数,可以(至少在原则上)处理浮点和整数意味着更少的函数,这是一件好事;
  • int版本足够简单(模数溢出和例外情况),如果有必要,有人可以编写自己的代码,因此感觉不是绝对必要的(还有其他几个类似的功能也可能是在标准库中提供,但可能由于类似原因未包括在内);
  • 如何处理溢出? IEEE-754已经指定了如何处理浮点数的所有令人讨厌的异常情况,但对于整数,你必须自己选择:使用errno?限制输入参数?不保证溢出任何东西?每个整数类型应该有一个版本吗?或者只是一个返回long的人?如果是这样,那么人们肯定会抱怨缺少int版本和short版本......
  • 对于整数来说,pow的最有用的案例之一是当基数为2时,在这种情况下,移位可能更有效。试图提供一种有效的功能来检测这种情况(否则,人们会开始争论是否应该使用轮班或致电ipow,然后进行更多的讨论......),以及当基数为4时,或者8,或1或0等,成为图书馆开发人员的真正问题。

最后,这个假设的ipow函数要么具有非常详细和过度指定的描述(提及性能方面),要么缺乏可见性:开发人员是否应该可靠地期望他们的ipow函数针对特殊情况进行优化?用户可能最终编写自己的版本以更好地理解其行为,因为这是一个相对简单的功能,不同的实现将会比比皆是。

总而言之,从用户的角度来看,int pow()似乎缺乏,但从图书馆开发人员和维护人员的角度来看,他们可能不愿意承担另一个负担,对于可以说有限的利益。

甚至有可能将库的早期版本考虑在内,然后经过一些讨论意识到它有几个缺点,并决定将其从API中删除。

答案 1 :(得分:1)

Anol的答案是非常重要的,我认为这是最正确的评估,为什么int pow()不是标准库的一部分,但是我想用另一种可能性修改它。

pow函数最有用的方面是能够正确地(至少就浮点运算而言)对非整数幂执行求幂。使用整数数学实现这种类型的行为是非常重要的,更不用说浮点数学了。他们决定要求两者中更有用的,而不是要求库实现者同时编写整数取幂例程和浮点求幂例程。它还有助于x87指令集以及许多其他FPU指令集提供内置的浮点取幂指令,以使软件方面的实现变得微不足道。

C也没有任何异常的概念,也没有可能暴露CPU标志之类的语言级全局状态。这将使int pow()实现中的溢出检测难以提供。对于double pow(),在特殊情况下,它只能返回非信令NaNInfinity。但是,整数世界中没有NaNInfinity的概念。

如果是例外,程序可以执行以下操作之一:

  • 无声地溢出
  • 返回INT_MININT_MAX
  • 更改调用者
  • 为其指定函数的整数
  • 更改某些全局状态,例如errno
  • 发出SIGFPE
  • 提供可用于模拟呼叫的姐妹函数int pow_overflow_check()

这些都不可取。前两个选项将导致在程序的可能不相关的区域中难以诊断逻辑错误。第三个将为使用该功能提供烦人且麻烦的障碍。第四个会破坏任何类型的重入保证。第五种选择会使整个计划陷入停顿。第六个选项可以很好地工作,但也会使标准更加膨胀,并使功能使用起来比第三个选项更麻烦。

此外,就像其他人所说的那样,对整数幂的求幂,特别是如果基数为2,则实现起来是微不足道的。对数学有基本了解的第一年compsci学生应该能够制定出适合大多数用例的正确实现。

最初的C语言主要针对汇编程序员,这是其中一个症状。语言规范中一个非常常见的主题是语言库应该只提供无法以可移植的方式实现in-language的东西,或者非常简单地实现纯粹的语言,特别是当有通用的CPU时/ FPU指令可以为您完成。

答案 2 :(得分:0)

这可能是保持旧标准简单的决定。虽然较新的标准包含了类似的功能,但是从来没有使用简单的int参数或返回值实现您喜欢的功能,目的是防止溢出问题,因为此处提供了其他答案。引用http://www.cplusplus.com/reference/cmath/pow/

  • C99

    double pow  (double base     , double exponent);
    float powf (float base      , float exponent);
    long double powl (long double base, long double exponent);
    

引用 Why isn't int pow(int base, int exponent) in the standard C++ libraries?

  

例如,C99理由文件明确提出   C89的两项指导原则限制了可以添加的内容:

     
    
        
  • 保持语言简洁。
  •     
  • 只提供一种方法来进行操作。
  •     
  

向原作者致信该主题的最佳答案。我相信,这个话题可能会完整地回答你的问题。