用MATLAB计算双精度误差?

用MATLAB计算双精度误差?,matlab,precision,Matlab,Precision,该值是绝对整数,不是一个值得怀疑的浮点数,而且,它与溢出无关,因为双精度值可以保持到2^1024 fprintf('%f',realmax) 17976931348623157000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

该值是绝对整数,不是一个值得怀疑的浮点数,而且,它与溢出无关,因为双精度值可以保持到2^1024

fprintf('%f',realmax)
179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
我在
nchoosek
函数中面临的问题是它不能生成精确的值

fprintf('%f\n',nchoosek(55,24));
2488589544741302.000000
而关于
binomian(n,m)=二项式(n-1,m)+二项式(n-1,m-1)
的百分比误差为2,如下所示

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

Ps:准确值为
24885895444741300


MATLAB有什么问题?

看起来像整数的东西(
55
)和实际上是整数的东西(就变量类型而言)之间有区别

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

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

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

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

请尝试:

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

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

看起来像整数(
55
)的东西和实际上是整数的东西(就变量类型而言)之间存在差异

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

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

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

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

请尝试:

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

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

类型,我没有访问MATLAB的权限,但是由于您显然可以使用Octave,因此我将基于此发布我的观察结果

如果您使用
edit nchoosek
查看倍频程源代码,或者您会发现计算二项式系数的公式非常简单:

A = round (prod ((v-k+1:v)./(1:k)));
如您所见,有
k
分区,每个分区都可能引入一些小错误。下一行试图提供帮助,并警告您可能会失去精度:

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

那么,如果我可以稍微修改一下你的最后一个问题,八度音阶有什么问题?我想说没有什么不对。作者显然知道不精确的可能性,并在出现这种可能性时包括了一个警告用户的检查。因此,该功能正在按预期工作。如果您的应用程序需要比内置函数提供的精度更高的精度,那么看起来您需要编写(或找到)某种代码,以更高的精度计算中间结果。

我没有访问MATLAB的权限,但由于您显然可以使用Octave,因此我将在此基础上发布我的观察结果

如果您使用
edit nchoosek
查看倍频程源代码,或者您会发现计算二项式系数的公式非常简单:

A = round (prod ((v-k+1:v)./(1:k)));
如您所见,有
k
分区,每个分区都可能引入一些小错误。下一行试图提供帮助,并警告您可能会失去精度:

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

那么,如果我可以稍微修改一下你的最后一个问题,八度音阶有什么问题?我想说没有什么不对。作者显然知道不精确的可能性,并在出现这种可能性时包括了一个警告用户的检查。因此,该功能正在按预期工作。如果您的应用程序需要比内置函数提供的精度更高的精度,那么您似乎需要编写(或查找)某种代码,以更高的精度计算中间结果。

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

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

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

ans =

2488589544741300

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

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

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

ans =

2488589544741300
非常感谢您的电子邮件