Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Variables 在MATLAB中,默认情况下变量真的是双精度的吗?_Variables_Matlab_Floating Point_Precision - Fatal编程技术网

Variables 在MATLAB中,默认情况下变量真的是双精度的吗?

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

这个问题产生于一些奇怪的事情,我在进一步调查后注意到

我一直认为MATLAB变量是默认值。所以,如果我要声明一个小数点后有20位的变量:

>> 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'