考虑下面的代码:
#include <iostream>
#include <cmath>
int main() {
int i = 23;
int j = 1;
int base = 10;
int k = 2;
i += j * pow(base, k);
std::cout << i << std::endl;
}
情况下输出“122”,而不是“123”。 它是在G ++ 4.7.2(MinGW的,Windows XP中)的错误吗?
std::pow()
的工作原理与浮点数,不具有无限的精度,也可能是标准库的实现您正在使用工具pow()
的(差)的方式,使这个缺乏无限精度变得重要。
然而,你可以很容易地定义你自己的版本,与整数工作。 在C ++ 11,你甚至可以让它constexpr
(这样的结果可能在编译时能够计算):
constexpr int int_pow(int b, int e)
{
return (e == 0) ? 1 : b * int_pow(b, e - 1);
}
这是一个活生生的例子 。
尾递归形式(学分丹尼森鲍姆 ):
constexpr int int_pow(int b, int e, int res = 1)
{
return (e == 0) ? res : int_pow(b, e - 1, b * res);
}
所有其他的答案为止错过或围绕这一问题的唯一问题舞蹈:
该pow
在C ++实现的质量不高。 当没有必要返回一个不准确的答案。
得到一个更好的C ++实现,或至少更换其中的数学函数。 在一个由Pascal Cuoq指向性好。
不与我至少包括:
$ g++ --version | head -1
g++ (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2)
$ ./a.out
123
IDEone还运行版本4.7.2,并给出123
。
的签名pow()
从http://www.cplusplus.com/reference/cmath/pow/
double pow ( double base, double exponent );
long double pow ( long double base, long double exponent );
float pow ( float base, float exponent );
double pow ( double base, int exponent );
long double pow ( long double base, int exponent );
你应该设置double base = 10.0;
和double i = 23.0
。
如果你简单的写
#include <iostream>
#include <cmath>
int main() {
int i = 23;
int j = 1;
int base = 10;
int k = 2;
i += j * pow(base, k);
std::cout << i << std::endl;
}
你认为什么是pow
应该是指什么? C ++标准甚至不保证其中CMATH你必须在全局范围战俘功能之后。
请记住,所有重载都至少在std
命名空间。 还有就是在pow
称取整数指数和有功能的pow
称取浮点指数函数。 这很可能是你的C ++实现仅声明在全局范围内的C战俘功能。 该函数接受一个浮点指数。 问题是,这个功能很可能有一对夫妇近似和舍入误差。 例如,实现该功能的一种可能的方式是:
double pow(double base, double power)
{
return exp(log(base)*power);
}
这很可能是战俘(10.0,2.0)产生类似99.99999999992543453265由于四舍五入的原因,并逼近误差。 的事实,浮点到整数转换合并产生小数点前这解释了您的122因为99 + 3 = 122结果的数目。
尝试使用POW的过载它接受一个整数指数和/或从浮做一些适当的四舍五入为INT。 超载将整数指数可能会给你确切的结果为10到第二电源。
编辑:
正如你指出的那样,试图使用的std :: POW(双,INT)超载似乎也产生一个值略少100我把检查ISO标准和的libstdc ++实现的时候,看到那个开头C ++ 11个取整数指数重载已经下降作为解决的结果, 缺陷报告550 。 启用的C ++ 0x / C ++ 11的支持实际上除去了的libstdc ++实现这可以解释为什么你没有看到任何改善的过载。
总之,它可能是一个坏主意,依靠特别是如果到整数转换涉及这样的功能的精确度。 向零略有误差显然有很大的不同,如果你期望一个浮点值,它是一个整数(如100),然后将其转换为int类型值。 所以我的建议是写自己的POW函数,它所有的整数或特别小心对于使用自己的回合功能,使轻微错误torwards零不改变结果的双> INT转换。
你的问题是不是在gcc的一个bug,那是绝对肯定的。 这可能是在执行中的错误pow
,但我觉得你的问题实在是简单的事实是,你正在使用pow
,因为它是为像实施这给出了一个不精确的浮点结果( exp(power * log(base));
和log(base)
是永远不会绝对准确[除非碱为e的功率。