Variables 在MATLAB中,默认情况下变量真的是双精度的吗?
这个问题产生于一些奇怪的事情,我在进一步调查后注意到 我一直认为MATLAB变量是默认值。所以,如果我要声明一个小数点后有20位的变量:Variables 在MATLAB中,默认情况下变量真的是双精度的吗?,variables,matlab,floating-point,precision,Variables,Matlab,Floating Point,Precision,这个问题产生于一些奇怪的事情,我在进一步调查后注意到 我一直认为MATLAB变量是默认值。所以,如果我要声明一个小数点后有20位的变量: >> num = 2.71828182845904553488; >> class(num) % Display the variable type ans = double 我希望忽略最后4位数字,因为顺序为10-16: 如果我尝试显示小数点后超过16位的数字(使用或),我会得到我期望看到的结果: >> fprintf
>> num = 2.71828182845904553488;
>> class(num) % Display the variable type
ans =
double
我希望忽略最后4位数字,因为顺序为10-16:
如果我尝试显示小数点后超过16位的数字(使用或),我会得到我期望看到的结果:
>> fprintf('%0.20f\n', num)
2.71828182845904550000
>> sprintf('%0.20f', num)
ans =
2.71828182845904550000
换句话说,数字17到20都是0
但是当我将num
传递给中的时,情况变得很奇怪,告诉它使用21位精度来表示数字:
>> vpa(num, 21)
ans =
2.71828182845904553488
什么最后4位数字已重新出现!当我输入的原始数字存储为双精度变量时,它们不应该丢失吗?既然num
在传递给vpa
时是一个双精度变量,vpa
如何知道它们是什么
我对正在发生的事情的最佳猜测是,MATLAB在内部表示的num
的精度比double高,因为我将其初始化为一个超过小数点的数字,而double-precision变量无法处理这个数字。是真的发生了这样的事,还是发生了其他事情
额外奖励:如果你没有偏头痛,那么这里还有一个额外的困惑来源
>> num = 2.71828182845904553488; % Declare with 20 digits past the decimal
>> num = 2.718281828459045531; % Re-declare with 18 digits past the decimal
>> vpa(num, 21)
ans =
2.71828182845904553488 % It's the original 20-digit number!!!
他们是双人的vpa()
只是选择显示超出浮点相对精度的非有效数字,其中printf()
和disp()
将它们截断或归零
您只能将原来的四位数字取出来,因为您选择初始化num
的文字恰好是二进制双精度值的精确十进制展开,因为它是从另一个问题的实际双精度值展开的输出中复制和粘贴的。正如您在“奖金”附录中所示,它对附近的其他值不起作用
更准确地说,Matlab中的所有数字文字都会生成double类型的值。它们被转换为最接近它们所表示的十进制值的二进制双精度值。实际上,超出双精度类型精度限制的文本中的数字会自动删除。当您复制并粘贴vpa
的输出以创建一个新变量时,就像另一个问题的海报对e=…
语句所做的那样,您是从一个文本初始化一个值,而不是直接处理前一个表达式的结果
这里的区别只是在输出格式上。我认为现在的情况是,vpa()
将双精度二进制double作为精确值处理。对于给定的二进制尾数指数值,可以计算相当于任意多个小数位数的小数。如果二进制值的精度(“宽度”)有限,就像处理任何固定大小的数据类型一样,那么只有那么多的十进制数字是有效的printf()
和Matlab的默认显示通过截断输出或将非有效数字显示为0来处理此问题vpa()
正在忽略精度限制,并继续根据您的要求计算小数位数
这些额外的数字是假的,因为如果它们被其他值替换以产生一个接近的十进制值,它们都会被“舍入”为相同的二进制双精度值
这里有一个方法来展示它。当以双精度存储时,x的这些值都是相同的,并且都用vpa()
表示
这是另一种证明它的方式。这是两个彼此非常接近的双人间
x0 = exp(1)
x1 = x0 + eps(x0)
vpa(x0)
和vpa(x1)
应产生与第16位数字相差很大的输出。但是,您不应该能够创建一个双值x
,这样vpa(x)
将产生介于vpa(x0)
和vpa(x1)
之间的十进制表示
(更新:Amro指出,您可以使用fprintf(“%bx\n',x)
以十六进制格式显示基础二进制值的精确表示。您可以使用此选项确认文本映射到同一个双精度。)
我怀疑vpa()
的行为是这样的,因为它将其输入视为精确值,并且多态性地支持符号工具箱中的其他Matlab类型,这些类型的精度比双倍精度高。这些值需要通过数字文字以外的方式初始化,这就是为什么sym()
将字符串作为输入,并且vpa(exp(1))
不同于vpa(sym('exp(1))
有道理吗?对不起,我的话太多了
(注意,我没有符号工具箱,因此我无法自己测试vpa()
)首先:
sprintf和fprintf在不同版本的MATLAB上似乎有不同的行为
例如,在MATLAB 2018 a中
num=2.7182818284590666666666;
sprintf('%0.70f', num)
ans =
'2.7182818284590668511668809514958411455154418945312500000000000000000000'
第二:
浮点数
MATLAB®表示双精度或单精度格式的浮点数。默认值为双精度,但您可以使用简单的转换函数将任意数字设置为单精度
双精度浮点
MATLAB根据IEEE®标准754构建双精度(或双精度)数据类型以实现双精度。任何存储为双精度的值都需要64位,格式如下表所示:
位:63用法:符号(0=正,1=负) 比特:62至52 用法:指数,偏移1023 位:51到0 用法:数字1.f的分数f 在252=4503599627370496和253=9007199254740992之间,可表示的数字正好是整数。对于t
x0 = exp(1)
x1 = x0 + eps(x0)
num=2.7182818284590666666666;
sprintf('%0.70f', num)
ans =
'2.7182818284590668511668809514958411455154418945312500000000000000000000'
a = vpa(1/3, 4)
a =
0.3333
vpa(a, 20)
ans =
0.33333333333303016843
sprintf('%0.28f', 8.0)
ans =
'8.0000000000000000000000000000'
sprintf('%0.28f', 8.1)
ans =
'8.0999999999999996447286321199'
sprintf('%0.28f', 64.1)
ans =
'64.0999999999999943156581139192'