Matlab单精度转双精度的错误

5

请问为什么在Matlab(R2016a)中使用double()将单精度浮点数转换为双精度浮点数后,最后几位数字会发生变化?以下是一个例子:

format 'long'
x=3.2530601; %arbitrary single precision number
x_s=single(x);
x_d=double(x_s);

如果我查看变量的类和值,我可以看到以下内容:xx_d 是双精度浮点数,x_s 如预期一样是单精度浮点数。它们的值分别是:
x=3.253060100000000
x_s=3.2530601
x_d=3.253060102462769

既然数字3.2530601可以表示为双精度或单精度浮点数,我不明白为什么xx_d不相同。它们的距离比x+eps(x)还要远。我想也许Matlab试图通过有理分数逼近来计算双精度x_d,但调用rat(x,16)并不会给出与x_d相同的结果。我一无所知。有人知道这里发生了什么吗?


3
我不使用Matlab,因此我将这个假设作为一条注释而不是回答。3.2530601无法用单精度或双精度浮点数表示。这个十进制数被转换成二进制浮点数,结果并不完全等于3.2530601。Matlab使用类型(single或double)来决定默认显示多少位数字。当值为single时,Matlab只显示“3.2530601”。当值转换为double时,值不会改变,但Matlab会从中显示更多数字。额外的数字使您能够看到该值不是3.2530601。 - Eric Postpischil
是的,它们比 x+eps(x) 更远。但是,它们没有比 x+eps(x_s) 更远。eps(x_s) 是 2.4e-7。你转换时的“误差”是 2.4e-9,这更小。基本上,当你将其转换为单精度时,2.4e-7 是你能得到的最精确的结果。因此,将其强制转换回双精度,这就是你真正可以期望的全部。 - Aero Engy
感谢您的评论。你们都是正确的。事实证明,认为Matlab会使用“format 'long'”显示浮点数的所有小数位数是错误的。使用“num2str(x_s,16)”可以发现,“x_d”和“x_s”在前16位上是相同的。 - David
1个回答

7

有两个密切相关的问题(在MATLAB中,默认情况下变量是否真正双精度?为什么24.0000在MATLAB中不等于24.0000?),你应该意识到这一点,但是它们并没有完全解决...

当计算给定尾数和浮点值指数的十进制等效值时,您可以将其计算到任意小数位数,但是超出浮点相对精度的任何位置最终都没有实际价值,通常甚至不显示。然而,在将低精度数字转换为高精度数字时,它们似乎会发挥作用。

让我们来看一下你的x_s值,既以正常方式显示(仅显示有效数字),又以vpa的方式显示它(带有任意数量的数字):

>> x_s = single(3.2530601)  % Create a single-precision number

x_s =

  single

   3.2530601

>> eps(x_s)  % Floating-point relative accuracy

ans =

  single

   2.3841858e-07

>> vpa(x_s, 16)  % Show 16 digits of precision, way more than the relative accuracy

ans =

3.253060102462769

>> x_d = double(x_s)  % Convert to double-precision

x_d =

   3.253060102462769

看这个!vpa中的数字与转换为双精度时获得的数字匹配。似乎在从single转换为double时,MATLAB会计算低精度值的十进制等价值,直到高精度值的位数,并使用该值进行初始化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接