使用 MATLAB 的二项式精度误差?

Accuracy error in binomials using MATLAB?

该值是绝对整数,不是浮点数值得怀疑,而且,它不是溢出,因为双精度值可以保持到 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

this demo shows

MATLAB 有什么问题?

看起来像整数 (55) 的东西和实际上是整数的东西(在变量类型方面)是有区别的。

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

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

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

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

试试看:

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

注意:%d 而不是 %f,将两个输入都转换为具体的整数。这里nchoosek的输出应该是int64.

类型

我无法访问 MATLAB,但由于您显然可以使用 Octave,我将 post 基于此进行观察。

如果您使用 edit nchoosekhere 查看 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 有什么问题?我会说没有错。作者显然知道不精确的可能性,并包括一个检查以在这种可能性出现时警告用户。所以该功能按预期工作。如果您的应用程序需要比 built-in 函数提供的更高的精度,看起来您需要编写(或找到)一些东西来计算更精确的中间结果。

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

如果符号工具箱可用,最容易实施的解决方案是使用它:

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

ans =

2488589544741300