我正在尝试将2、3位数字相乘。 我使用了2个循环(嵌套),并将num1的每个数字与num2相乘, 并使用pow()将每个结果移到适当的位置。 所以问题是pow(10,3)变成299而不是300。
我没有做太多尝试,但是使用printf来查找运行时实际发生的事情,这就是我所发现的。
移位后的tempR值应为
5,40,300,100,800,6000,1500,12000,90000
但作为
5,40,299,100,799,6000,1500,12000,89999
int main(void)
{
int result; // final result
int tempR; // temporary for each iteration
char a[] = "345"; // number 1
char b[] = "321"; // number 2
for(int i = 2;i>= 0 ; i --)
{
for(int j = 2;j >= 0 ; j --)
{
int shift = abs(i-2 + j -2);
printf("%d\n",shift); //used to see the values of shift.
//and it is coming as expected
tempR = (int)(b[i] - '0') * (int)(a[j] - '0');
printf("%d \n",tempR); // value to tempR is perfect
tempR = tempR*pow(10,shift);
printf("%d \n",tempR); // here the problem starts
result += tempR;
}
}
printf("%d",result);
}
答案 0 :(得分:2)
尽管需要IEEE754(在台式机系统上无处不在)为某些运算符(例如加,乘,除和减)以及某些功能(例如sqrt
)返回最佳的浮点值,但这确实不是适用于pow
。
pow(x, y)
可以并且经常被实现为exp(y * ln (x))
。希望您能看到,当pow
与看似微不足道的整数参数一起使用时,结果可能会“消失”,并且结果被截断为int
。
那里有C实现比您拥有的pow
更准确的实现,尤其是对于整数参数。如果需要这样的精度,则可以将工具集移至这样的实现。从受尊重的数学库中借用pow
的实现也是一种选择,否则请自行承担。如果您了解我的意思,那么使用round
也是一种技巧。
答案 1 :(得分:1)
切勿将浮点函数用于整数计算。您的战俘结果几乎永远不会是精确的。在这种情况下,它略低于300,而对整数的转换为299。
答案 2 :(得分:0)
pow
函数用于双精度。双打使用有限精度。转换回整数,而不是四舍五入。
有限精度类似于将1/3表示为0.333333
。如果您进行9 * 1/3
并切成整数,则将得到2而不是3,因为9 * 1/3
将给2.999997
切成2。
这种四舍五入方法使您一筹莫展。您也可以在切成整数之前加0.5来取整,但我不建议这样做。
如果您希望得到确切的答案,请不要将整数传递给双精度数,也不能返回。
答案 3 :(得分:-1)
其他人提到pow
不能产生准确的结果,如果将结果转换为整数,则很可能会损失精度。特别是因为如果将浮点类型分配给整数类型,结果将被截断而不是四舍五入。在此处阅读更多信息:Is floating math broken?
最方便的解决方案是编写您自己的pow的整数变体。看起来可能像这样:
int int_pow(int num, int e)
{
int ret = 1;
while(e-- > 0)
ret *= num;
return ret;
}
请注意,如果e
为负或num
和e
均为0时,它将不起作用。它也没有溢出保护。它只是说明了这个想法。
在您的特定情况下,您可以根据10写一个非常专业的变体:
unsigned int pow10(unsigned int e)
{
unsigned int ret = 1;
while(e-- > 0)
ret *= 10;
return ret;
}