最近我写了一段代码:
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
有人给我解释一下吗?非常感谢你!
答案 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}时,上面代码中的变量res
,int
和int
都是double
类型} double
,可能导致精度损失。例如(可能不严格),浮点单元(FPU)按C ++中的类型转换计算int
,然后计算pow(10, 4)=9999.99999999
。
更改代码:
const int num = 10; for(int i = 0; i < 5; ++i){ double res = pow(num, i); cout << res << endl; }
替换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;
}