Matlab中有一个函数名为eps

  • 格式:doc
  • 大小:23.00 KB
  • 文档页数:2

下载文档原格式

  / 2
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Matlab中有一个函数名为eps,文档中对这个函数的说明是:Floating-point relative accuracy.它的具体功能是什么呢?

数字计算机所处理和存储的数据,都是量化过的数据,因此不能拥有任意的精度。对于以整数形式保存的数据,数与数的最小间隔为1,不能再小。而float类型同样,数与数之间存在一个最小间隔,但这个间隔并不是常数,而是随着数字的大小而改变的。举一个简单的例子,我们用科学计数法来表示数值,规定尾数部分只能保留一位小数。那么1.0×102,与它相邻的数字有1.1×102,处在这两个数中间的数值无法精确表示,因为只能保留一位小数。这两个相邻的数字的间隔是多少呢?1.1×102-1.0×102=10。也就是说,在这种计数方式的制约下,我们所能表示的数都是以十为间隔。但是这并不是一成不变的,对于1.0×103而言,与它相邻的数有1.1×103,处于这两个数中间的数值无法精确表示。它们的间隔是1.1×103-1.0×103=100。此时我们能够用这种计数方式表示的数以100为间隔。可见数值越大,精度越低。

对于使用二进制存储浮点数的754标准而言,relative accuracy与上面所描述的十进制的情况类似。754标准所规定的存储方式与科学计数法很相似,但是有一些细节问题需要注意,如最高位的1不存储,指数部分的偏移量,inf,NaN的存储方式等等。

想要完全了解relative accuracy,一个简单的方法是自己实现一个eps函数,并与Matlab自备的eps进行比较。我试着写了一个,值得注意的是我所使用的版本是Matlab 7.7,代码中使用了typecast函数,该函数在7.x的早期版本中不存在。还有一点就是此代码用于常见的Intel处理器+Windows操作系统,如果在其它架构上编写类似代码,好像要考虑大小端模式的问题。

my_eps.m:

function r=my_eps(d)

d=abs(d);

if ((d==inf) || isnan(d))

r=NaN;

return;

end

bytes=typecast(d,'uint8');

e=typecast(bytes(end-1:end),'uint16');

switch class(d)

case'double',

bs=4;

subnum=52;

zeronum=6;

le_rmin=2^(-1074);

case'single',

bs=7;

subnum=23;

zeronum=2;

le_rmin=2^(-149);

otherwise,

error('Only Single & Double classes are supported!');

end

if (d<=realmin(class(d)))

r=le_rmin;

return;

end

e=bitshift(e,-bs)-subnum;

e=bitshift(e,bs);

e=typecast(e,'uint8');

r=typecast([zeros(1,zeronum,'uint8') e],class(d));

这段代码很简单,为了说明其原理,还是以十进制的科学计数法为例(假设只能保留一位小数):

对于一个数,想要知道与它与其最相邻的数之间的间隔,只要保持该数的指数部分不变,尾数部分最右边的那一位为1,其余为0即可,例如,我想知道1.2×108与相邻数之间的间隔,保持指数部分不变,尾数只有最右边一位为1,其余为0,得到:0.1×108。但事情并没有结束,得到的这个数的形式并不符合规范,我们必须保证尾数部分个位为1才行,所以要将尾数左移一位,左移的同时,要减少指数,移一位,指数就要减1,最终符合规范的数值是1.0×107。

原理是这样,但技术上的问题比较烦人。先看一下double类型的存储格式:

SEEE EEEE EEEE MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM

S代表符号位,E代表指数位,M代表尾数。为了取得指数的数值,须将最左边的两个字节左移4位:

0000 0EEE EEEE EEEE

然后将尾数部分的最右边一位置1,其余为0。为了符合规范,须将这个唯一的1移动到尾数的各位上,这一操作一共要左移52位,相应的,指数部分要减52。my_eps函数的最后几行就是完成这样的操作。

float类型的操作类似,只是存储格式有些许差别,为:

SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM

最后,还有一点值得注意,即判断一个变量是否是NaN,不要写成d==NaN,Matlab 规定NaN≠NaN。正确的做法是使用isnan函数进行判断。