为什么在C ++中pow(10,5)= 9,999

时间:2012-03-14 14:45:28

标签: c++ mingw pow

最近我写了一段代码:

const int sections = 10;

for(int t= 0; t < 5; t++){
   int i = pow(sections, 5- t -1);  
   cout << i << endl;
}

结果是错误的:

9999
1000
99
10
1

如果我只使用此代码:

for(int t = 0; t < 5; t++){
    cout << pow(sections,5-t-1) << endl; 
}

问题不再发生:

10000
1000
100
10
1

有人给我解释一下吗?非常感谢你!

9 个答案:

答案 0 :(得分:12)

由于浮点值的表示pow(10.0, 5)可能是9999.9999999或类似的东西。当您将其分配给被截断的整数时。

编辑:如果cout << pow(10.0, 5);看起来输出已四舍五入,但我现在没有任何支持文件确认。

编辑2:BoBTFish和this question发表的评论确认,在pow(10.0, 5)中直接使用cout时,该问题正在逐渐展开。

答案 1 :(得分:2)

当与分数指数一起使用时,pow(x,y)通常被评估为exp(log(x)*y);如果以无限精度进行求值,这样的公式将在数学上校正,但实际上可能导致舍入误差。正如其他人所指出的,当转换为整数时,值9999.999999999将产生9999.当使用具有浮点指数的取幂运算符时,某些语言和库一直使用这样的公式。其他人尝试识别指数何时是整数,并在适当时使用迭代乘法。查找pow函数的文档,当x为负数且y没有小数部分(x为负数且{{1}时,它似乎有效是偶数,结果应为`y;当pow(-x,y)为奇数时,结果应为y。当-pow(-x,y)没有小数部分时,似乎合乎逻辑要经历处理负y值的麻烦的库应该使用迭代乘法,但我不知道有任何规定它必须。

在任何情况下,如果你试图将一个整数提升到一个幂,几乎可以肯定最好使用整数数学进行计算,或者如果要引出的整数是常数或者总是很小,只需使用查找表(通过适合64位整数的任何幂提高0到15之间的数字只需要4,096项表)。

答案 2 :(得分:2)

来自Here

查看pow()函数:double pow (double base, double exponent);我们知道参数和返回值都是double类型。但是,在将num转换为i或{{1}时,上面代码中的变量resintint都是double类型} double,可能导致精度损失。例如(可能不严格),浮点单元(FPU)按C ++中的类型转换计算int,然后计算pow(10, 4)=9999.99999999

如何解决?

解决方法1

更改代码:

    const int num = 10;

    for(int i = 0; i < 5; ++i){
       double res = pow(num, i);
       cout << res << endl;
    }

溶液2

替换int(9999.9999999)=9999类型中具有更高计算精度的浮点单元(FPU)。例如,我们在Windows CPU中使用SSE。在Code :: Block 13.12中,我们可以执行以下步骤来实现目标:设置 - &gt;编译器设置 - &gt; GNU GCC编译 - &gt;其他选项,添加

double

图片如下:

add <code>-mfpmath=sse -msse3</code> http://aleeee.qiniudn.com/change%20SSE%20in%20CB.png

答案 3 :(得分:1)

发生的事情是pow函数返回一个double 当你这样做时

int i = pow(sections, 5- t -1);  

小数.99999削减,你得到9999。

直接打印或将其与10000进行比较不是问题,因为它在某种意义上是无效的。

答案 4 :(得分:1)

如果您的第一个示例中的代码是您正在运行的确切代码,那么您将拥有一个错误的库。无论你是拿起std::pow还是C pow都需要双打,即使选择了双版本,10也可以表示为double。因此,取幂可以完全表示为double。不应该发生舍入或截断或类似的事情。

使用g ++ 4.5,即使使用-ffast-math-O3,也无法重现您的(奇怪)行为。

现在我怀疑发生的事情是sections 直接分配文字10,而是在内部读取或计算,使其值类似于{{1} },当被提升到第四个幂时会产生类似9.9999999999999的数字。然后将其截断为显示的整数9999。

根据您的需要,您可能希望在分配到int之前对源编号或最终编号进行舍入。例如:9999.9999999

答案 5 :(得分:0)

全局命名空间中必须有一些损坏的pow函数。然后,由于ADL,std::pow会在第二个示例中“自动”使用。

或者t实际上是第一个示例中的浮点数量,并且您正在遇到舍入错误。

答案 6 :(得分:0)

第一段代码中的t类型是什么?如果它不是int,那可能是一个舍入问题。

答案 7 :(得分:0)

您将结果分配给int。这会强制它,截断数字。

这应该可以正常工作:

for(int t= 0; t < 5; t++){
   double i = pow(sections, 5- t -1);  
   cout << i << endl;
}

答案 8 :(得分:0)

发生的事情是您的答案实际上是99.9999,而不是100。这是因为pow是双精度的。因此,您可以使用i = ceil(pow())来解决此问题。

您的代码应为:

const int sections = 10;
for(int t= 0; t < 5; t++){
   int i = ceil(pow(sections, 5- t -1));  
   cout << i << endl;
}