我试图实现一个简单的组合功能
private int combination(int n, int k)
{
if(n>>1 < k)
k = n - k;
double mul = 1;
for(int i=n+1-k;i<n+1;i++)
mul *= i;
for(int i=k;i>0;i--)
mul /= i;
return (int)mul;
}
当我将参数作为combination(33,17)
输入时,它会给我 1166803109 ,但正确的数字应为 1166803110 。所以我在截断到int之前打印出mul
变量,它给了我一个十进制数: 1.1668031099999998E9 ,这让我很困惑。根据定义,它应该是一个完美的分区,为什么它给我一个小数?
答案 0 :(得分:2)
当谈到像float
或double
这样的浮点类型时,很少有完美的除法(在浮点结果是整数的意义上是完美的)。这是因为值在内部表示的方式;执行计算时会有一些精度损失。 (这类似于计算机将2/3
划分为0.666667
的原因。)而不是使用double
,而是坚持使用int
或{{1}等整数类型如果您的计算可能达到大于long
可以容纳的值,请使用BigInteger
或类似内容。
答案 1 :(得分:1)
由于internal representation,浮点运算并不完全准确。
由于您只对结果的整数表示感兴趣,因此可以使用Math.round()
你的方法应该是这样的:
private int combination(int n, int k)
{
if(n>>1 < k)
k = n - k;
double mul = 1;
for(int i=n+1-k;i<n+1;i++)
mul *= i;
for(int i=k;i>0;i--)
mul /= i;
return (int) Math.round(mul);
}
输出:
System.out.println(combination(33,17));
1166803110