2016-01-23 102 views
0

该值是绝对整数,不是一个值得怀疑的浮点数,并且它不是溢出,因为double值可以保持到2^1024。使用MATLAB的二项式的精度错误?

fprintf('%f',realmax) 
179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 

我面临nchoosek功能,它不准确产生的问题重视

fprintf('%f\n',nchoosek(55,24)); 
2488589544741302.000000 

虽然它是2关于该binomian(n,m)=binomial(n-1,m)+binomial(n-1,m-1)如下百分比误差

fprintf('%f',nchoosek(55-1,24)+nchoosek(55-1,24-1)) 
2488589544741301.000000 

ps:确切的数值是2488589544741300

this demo shows

MATLAB有什么问题?

回答

2

您对realmax函数的理解是错误的。这是可以存储的最大值,但是如此大的数字会导致浮点精度误差远高于1.不能存储在双精度值中的第一个整数为2^53+1,请尝试2^53==2^53+1作为一个简单示例。

如果符号工具箱是可用的,实现的解决方案最简单的就是使用它:

>> nchoosek(sym(55),sym(24)) 

ans = 

2488589544741300 
1

看起来像一个整数(55)的东西与实际上是一个整数(根据变量类型)之间有区别。

您计算的方式,您的值存储为浮点数(这是realmax指向您的最大正浮点数 - 检查intmax('int64')为最大可能的整数值),因此您可以获得浮点错误。大数值的绝对差值2并不意外 - 实际百分比误差很小。

另外,您在格式字符串中使用了%f - 例如,要求它显示为浮点。

对于nchoosek,具体来说,从文档中,输出作为与输入n和k相同类型的非负标量值返回,或者如果它们是不同类型的非双类型(仅限于如果一个是双精度型,则有不同的输入类型)。

在Matlab中,当您直接在函数输入中输入数字时,它通常默认为浮点数。你必须强制它是一个整数。

尝试代替:

fprintf('%d\n',nchoosek(int64(55),int64(24))); 

注:%d%f,转换两个输入具体整数。 nchoosek的输出应该是int64

+1

非常感谢你的努力,但[希望你在张贴之前检查你的代码(HTTP:// ideone的.com/rP8kEG) – Abra001

1

我无法访问MATLAB,但由于您明显可以使用Octave,因此我会发布基于此的观察结果。

如果你看一下使用edit nchoosek或倍频源代码here,你会看到,计算二项式系数的公式很简单:

A = round (prod ((v-k+1:v)./(1:k))); 

正如你所看到的,有k区,每个区有可能引入一些小错误。下一行尝试是有益的,警告你的精度损失的可能性:

if (A*2*k*eps >= 0.5) 
    warning ("nchoosek", "nchoosek: possible loss of precision"); 

所以,如果我可以稍微修改你的最后一个问题,什么是错的八度?我会说没有错。作者显然知道不准确的可能性,并且包含一个检查,以在有可能出现时警告用户。所以这个功能按照预期工作。如果您的应用程序需要比内置函数提供的更高的精度,则看起来您需要编写(或查找)以更高精度计算中间结果的内容。