[英]Matlab nchoosek got difference answer using int64 and sym
这是关于Matlab中的nchoosek
函数的问题。
我想找到nchoosek(54,25)
,它与54C25相同。 由于答案约为10 ^ 15,因此我最初使用int64
。 但是,关于象征性答案,答案是错误的。
输入:
nchoosek(int64(54),int64(25))
nchoosek(sym(54),sym(25))
输出:
1683191473897753
1683191473897752
您会看到它们相差一个。 由于我现在使用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))
int64(prod(nums./dens))
prod(sym(nums)./sym(dens))
。 每个人都一样吗?
我在R2014a上没有这个问题:
>> n = int64(54);
>> k = int64(25);
>> nchoosek(n,k)
ans =
1683191473897752 % class(ans) == int64
>> nn = sym(n);
>> kk = sym(k);
>> nchoosek(nn,kk)
ans =
1683191473897752 % class(ans) == sym
% N!/((N-K)! K!)
>> factorial(nn) / (factorial(nn-kk) * factorial(kk))
ans =
1683191473897752 % class(ans) == sym
如果检查函数edit nchoosek.m
的源代码,您会看到它专门使用单独的算法处理64位整数的情况。 我不会在这里重现代码,但是这里是重点:
function c = nchoosek(v,k)
...
if int64type
% For 64-bit integers, use an algorithm that avoids
% converting to doubles
c = binCoef(n,k,classOut);
else
% Do the computation in doubles.
...
end
....
end
function c = binCoef(n,k,classOut)
% For integers, compute N!/((N-K)! K!) using prime factor cancellations
...
end
@Amro在nchoosek
中显示int64或unit64的classOut的特殊情况,
但是在2013a中,仅当答案介于
flintmax
(不带参数)和 double(intmax(classOut)) + 2*eps(double(intmax(classOut)))
对于int64
,它给出了9007199254740992和922337203685477575808,而解决方案并不位于...
如果解决方案落在这些值之间,则将使用子函数binCoef
重新计算其帮助状态: 对于整数,请使用质因子抵消来计算N!/(((NK)!M!)
对于给定的int64输入, binCoef
函数将产生正确的答案
binCoef
不被调用 而是使用“默认”帕斯卡三角形方法,其中:
((n-k+1):n)./(1:k)
的乘积 k
双精度表示。 因此,我们几乎可以肯定是浮点错误 。
我可以看到两个选择;
&& c >= flintmax
删除该表达式将迫使Matlab对int64和uint64的输入中精度范围内的任何值使用更精确的基于整数的计算。 这会稍慢一些,但会避免浮点错误,这在使用整数类型时理应是意外的。
选项一- 应该相当简单...
选项二-我建议保留原始功能的不变备份,或使用修改内容复制该功能,然后改用该功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.