2

nchoosekMatlabの関数についての質問です。

nchoosek(54,25)54C25と同じを探したいです。答えは10^15くらいなので、本来は を使いますint64。しかし、象徴的なものに関しては答えが間違っています。

入力:

nchoosek(int64(54),int64(25))
nchoosek(sym(54),sym(25))

出力:

1683191473897753
1683191473897752

1 つずつ異なることがわかります。私は現在 を使用しているので、これは実際には緊急の問題ではありませんsym。しかし、誰かがなぜこれが起こるのか教えてもらえますか?


編集:

R2013aを使用しています。

を見てみるとnchoosek.m、入力が にある場合int64、コードは次のように単純化できることがわかります。

function c = nchoosek2(v,k)

    n = v;  % rename v to be n. the algorithm is more readable this way.

    classOut = 'int64';
    nd = double(n);
    kd = double(k);
    nums = (nd-kd+1):nd;
    dens = 1:kd;
    nums = nums./dens;      %%
    c = round(prod(nums));
    c = cast(c,classOut);
end

しかし、結果は私int64(prod(nums./dens))とは異なりprod(sym(nums)./sym(dens))ます。これは誰にとっても同じですか?

4

2 に答える 2

1

2013aでは、これを再現できます...

nchoosek@Amro が int64 または unit64 の classOut の特別なケースを示しているように
、2013a では、これは答えが間にある場合にのみ適用されます。

  • flintmax(引数なし) および
  • double(intmax(classOut)) + 2*eps(double(intmax(classOut)))

これint64は 9007199254740992 & 9223372036854775808 を与えますが、その解は間にありません...


解がこれらの値の間にある場合binCoef 、ヘルプに次のように記載されているサブ関数を使用して再計算されます。整数の場合、素因数のキャンセルを使用して N!/((NK)! M!) を計算

binCoef関数は、指定された int64 入力に対して正しい答えを生成します。

2013a では、これらの入力binCoefは呼び出されません

代わりに、「デフォルト」のパスカル三角形法が使用されます。

  • 入力は double にキャストされます
  • ベクトルの積を((n-k+1):n)./(1:k)取る
  • このベクトルにkは分数の double 表現が含まれます。

したがって、ほぼ確実に浮動小数点エラーが発生します。


何ができるでしょうか?

私が見ることができる2つのオプション;

  1. binCoef のコードに基づいて独自の関数を作成し、
  2. nchoosek を変更し、&& c >= flintmax81 行目から削除します。

この式を削除すると、Matlab は int64 および uint64 の入力に対して、精度内の任意の値に対してより正確な整数ベースの計算を使用するようになります。これは少し遅くなりますが、浮動小数点エラーを避けることができます。浮動小数点エラーは、整数型を操作するときに当然予想外です。

オプション 1 -かなり簡単なはずです...

オプション 2 - 元の関数の変更されていないバックアップを保持するか、変更を加えた関数のコピーを作成して代わりに使用することをお勧めします。

于 2014-10-14T10:49:16.063 に答える