该值是绝对整数,不是要被怀疑的浮点数,而且,它不是溢出,因为double值可以保持到2 ^ 1024。
fprintf('%f',realmax)
179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
我在nchoosek
函数中遇到的问题是它没有产生确切的值
fprintf('%f\n',nchoosek(55,24));
2488589544741302.000000
虽然关于binomian(n,m)=binomial(n-1,m)+binomial(n-1,m-1)
的百分比误差为2,如下所示
fprintf('%f',nchoosek(55-1,24)+nchoosek(55-1,24-1))
2488589544741301.000000
Ps:确切的值为2488589544741300
MATLAB有什么问题?
答案 0 :(得分:2)
您对realmax
功能的理解是错误的。它是可以存储的最大值,但是如此大的数字,你的浮点精度误差远高于1.第一个不能存储在double值中的整数是2^53+1
,try { {1}}这是一个简单的例子。
如果符号工具箱可用,最容易实现的解决方案是使用它:
2^53==2^53+1
答案 1 :(得分:1)
看起来像整数(55
)的东西和实际上是整数的东西(就变量类型而言)之间存在差异。
你计算它的方式,你的值存储为浮点(这是realmax
指向你的 - 最大正浮点数 - 检查intmax('int64')
是否有最大可能的整数值),这样你就可以得到浮点错误。大值中的绝对差值2并非意料之外 - 实际百分比误差很小。
另外,您在格式字符串中使用%f
- 例如要求它显示为浮点。
对于nchoosek
具体而言,从文档中,输出作为非负标量值返回,与输入n和k的类型相同,或者,如果它们是不同类型,则返回非双重类型(如果只有一个输入类型,你只能有不同的输入类型。
在Matlab中,当您直接在函数输入中键入数字时,它通常默认为浮点数。你必须强迫它是一个整数。
尝试改为:
fprintf('%d\n',nchoosek(int64(55),int64(24)));
注意:%d
不是%f
,将两个输入转换为特定整数。此处nchoosek
的输出应为int64
类型。
答案 2 :(得分:1)
我无法访问MATLAB,但由于您显然可以使用Octave,我会发布基于此的观察结果。
如果您使用edit nchoosek
或here查看Octave源代码,您会发现计算二项式系数的公式非常简单:
A = round (prod ((v-k+1:v)./(1:k)));
如您所见,有k
个分区,每个分区都有可能引入一些小错误。下一行试图提供帮助,并警告您可能会失去精确度:
if (A*2*k*eps >= 0.5)
warning ("nchoosek", "nchoosek: possible loss of precision");
所以,如果我稍微修改你的最后一个问题,那么Octave有什么问题?我会说没有错。作者显然知道不精确的可能性,并包括检查以警告用户何时出现这种可能性。所以功能按预期工作。如果您的应用程序需要比内置函数更高的精度,那么您似乎需要编写(或查找)能够更精确地计算中间结果的内容。