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である必要があります。そのmulため、intに切り捨てる前に変数を出力すると、10進数の1.1668031099999998E9が返されますが、これは混乱を招きます。定義上、それは完全な除算でなければなりません、なぜそれは私に小数を与えるのですか?

4

2 に答える 2

2

floatまたはのような浮動小数点型doubleに関しては、完全な除算はめったにありません(浮動小数点の結果が整数であるという意味で完全です)。これは、値が内部的に表される方法によるものです。計算を実行すると、精度がいくらか失われます。(これは、除算2/3がコンピュータによってレンダリングされる理由と似てい0.666667ます。)を使用するのではなく、またはdoubleのような整数型を使用するか、計算が保持できる値よりも大きい値に達する可能性がある場合は、または同様のを使用します。intlongBigIntegerlong

于 2013-02-14T04:32:34.590 に答える
1

内部表現のため 、浮動小数点演算は完全に正確ではありません。

結果の整数表現のみに関心があるため、切り捨てる代わりに、次のようにしてdoubleを丸めることができます。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 に答える