我正在C ++中计算组合(15,7)。
我首先使用以下代码,并由于type promotion error而得到错误的答案。
#include <iostream>
int main()
{
int a = 15;
double ans = 1;
for(int i = 1; i <= 7; i++)
ans *= (a + 1 - i) / i;
std::cout << (int) ans;
return 0;
}
输出: 2520
因此我将ans *= (a + 1 - i) / i;
更改为ans *= (double)(a + 1 - i) / i;
,但仍然得到错误的答案。
#include <iostream>
int main()
{
int a = 15;
double ans = 1;
for(int i = 1; i <= 7; i++)
ans *= (double) (a + 1 - i) / i;
std::cout << (int) ans;
return 0;
}
输出: 6434
最后,我尝试了ans = ans * (a + 1 - i) / i
,它给出了正确的答案。
#include <iostream>
int main()
{
int a = 15;
double ans = 1;
for(int i = 1; i <= 7; i++)
ans = ans * (a + 1 - i) / i;
std::cout << (int) ans;
return 0;
}
输出: 6435
有人可以告诉我为什么第二个不起作用吗?
答案 0 :(得分:4)
如果打印出public void aButton() {
start = mediaPlayer.getCurrentPosition();
}
public void bButton() {
pressedCount += 1;
System.out.println("AB Button Count: " + pressedCount);
stop = mediaPlayer.getCurrentPosition();
mediaPlayer.seekTo(start);
if(mediaPlayer.getCurrentPosition() == stop){
mediaPlayer.seekTo(start);
}
}
而不将其投射到ans
上,将会看到第二个结果是(int)
。这很接近6434.9999999999990905052982270717620849609375
的正确答案,因此显然不再是类型提升错误。
不,这是经典的floating point inaccuracy。当您写6535
时,您所做的等同于:
ans *= (double) (a + 1 - i) / i
将此与第三个版本进行比较:
ans = ans * ((double) (a + 1 - i) / i);
前者先进行除法,然后相乘。后者从左到右操作,因此乘法先于除法。操作顺序的这种变化导致两者的结果略有不同。浮点计算对操作顺序极为敏感。
快速解决方案:不要截断结果; round。
更好的解决方法:请勿将浮点数用于积分算术。保存除法,直到完成所有乘法。使用ans = ans * (a + 1 - i) / i;
,long
甚至是big number library。
答案 1 :(得分:0)
第一个不起作用,因为那里有整数除法。
第二个和第三个之间的区别是:
ans = ans * (double(a + 1 - i) / i); // second is equal to this
vs:
ans = (ans * (a + 1 - i)) / i; // third is equal to this
所以差异是按乘法和除法的顺序进行的。如果您将双精度取整为整数而不是简单地舍弃小数部分,将会得到相同的结果。
std::cout << int( ans + 0.5 ) << std::endl;