0

我试图实现一个简单的组合功能

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,这让我很困惑。根据定义,它应该是一个完美的除法,为什么它给我一个小数?

4

2 回答 2

2

float当涉及到or之类的浮点类型double时,很少有完美的除法(完美的意思是浮点结果是一个整数)。这是因为值在内部表示的方式;执行计算时会损失一些精度。(这类似于为什么2/3计算机会将除法呈现为0.666667。)不要使用double,而是坚持使用 or 之类的整数类型,int或者如果您的计算可能达到大于 a可以容纳的值,请long使用or 类似的类型。BigIntegerlong

于 2013-02-14T04:32:34.590 回答
1

由于它们的 内部表示,浮点运算并不完全准确。

由于您只对结果的整数表示感兴趣,因此您可以舍入双精度而不是截断,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
于 2013-02-14T04:26:00.760 回答