Matlab 双精度数字:变量编辑器与 fprintf
Matlab Double Precision Digits: Variable Editor vs. fprintf
在this question之后,我在看Matlab中double变量的精度。在那里,建议使用 fprintf
更仔细地查看变量。
奇怪的是Variable Editor和fprintf
显示的结果不一样,fprintf多显示一位。
% pi
Variable Editor: 3.141592653589793
fprintf('0.16f\n',pi): 3.1415926535897931
vpa('pi'): 3.1415926535897932384626433832795
% pi / 180
pi180 = pi/180
Variable Editor (pi180) 0.017453292519943
fprintf('%0.16f\n',pi180) 0.0174532925199433
vpa('pi/180') 0.017453292519943295769236907684886
在内部,Matlab 似乎正在处理由 fprintf
打印的精度
>> fprintf('%0.16f\n',0.0174532925199433*10) % value from fprintf
0.1745329251994330
>> fprintf('%0.16f\n',0.017453292519943*10) % value from Variable Editor
0.1745329251994300
>> fprintf('%0.16f\n',pi180*10) % internal calculation
0.1745329251994330
为什么会这样?
如果我在函数中使用预先计算的 pi/180
,我应该使用来自 fprintf 还是来自变量编辑器的值?
tl;dr 在变量编辑器中,Matlab 在 15 位而不是 16 位处截断。
tl;dr MATLAB 中的变量使用双精度。命令 Window 和变量编辑器中的变量使用相同的精度。唯一的区别是显示格式和打印精度的小数位数。
默认情况下,MATLAB 对其变量使用双精度。 MATLAB 中的这些变量存储在工作区中。命令 Window 和变量编辑器都从同一个工作区中提取它们的变量,因此在下面使用相同的精度。
在变量编辑器和命令 Window 中显示变量的默认格式是 short
格式。您可以使用
检查命令 Window
>> get(0, 'format')
ans =
short
并通过转至 Preferences -> Variables -> Format
获取变量编辑器。默认情况下,short
格式将变量显示为精确到小数点后 4 位。
在我看来,您已将变量编辑器中变量的默认显示格式更改为 long
格式。此格式显示精度为 15 位小数的双精度变量。 long
和 short
格式都舍入变量,因此 pi
即 3.14159
被舍入为 3.1416
因为 9
在第 5 位小数short
格式显示时的位置
>> format short
>> pi
ans =
3.1416
这直接等同于fprintf
产生的输出
>> fprintf(1, '%.4f\n', pi);
3.1416
但是,long
格式,我猜,您已将变量编辑器设置为默认格式,四舍五入到小数点后 15 位,因此显示
>> format long
>> pi
ans =
3.141592653589793
直接等同于
>> fprintf(1, '%.15f\n', pi);
3.141592653589793
当您使用 fprintf(1, '%.16f\n', pi);
时,您将 pi
打印到小数点后 16 位,并且 而不是 15,这是由 long
格式指定的。这就是为什么你的输出是
>> fprintf(1, '%.16f\n', pi);
3.1415926535897931
注意,1
在这末尾。这就是为什么它前面的 3
在您的变量编辑器中显示时没有四舍五入为 4
的原因。
总结
- MATLAB 中的变量默认使用双精度
- MATLAB 变量存储在工作区
- 命令 Window 和变量编辑器中可用的变量均来自工作区并使用相同的精度
预先计算的值
在 MATLAB 中,您应该在函数调用或处理其他数值数据时使用变量名 pi180
。这将使用双精度并消除使用 fprintf
或变量编辑器输出的值可能出现的任何复制和粘贴错误。
fprintf
怪癖
tl;dr MATLAB 的 short
和 long
格式在 %d
、%.f
、[=49= 之间切换] 和 %.e
说明符取决于最合适的输入方法。
@horchler 指出 %.f
仅直接等同于特定输入的 short
和 long
格式,这是正确的。在 fprintf
和 MATLAB 的 short
和 long
格式之间,no 直接等效于 all 输入。
例如让我们看看 eps
和 100.5
并尝试打印与 MATLAB 的 short
和 long
格式完全相同的数字。
>> format short
>> eps
ans =
2.2204e-16
>> 100.5
ans =
100.5000
和
>> format long
>> eps
ans =
2.220446049250313e-16
>> 100.5
ans =
1.005000000000000e+02
现在我们从上面知道 fprintf(1, '%.4f\n', pi);
和 fprintf(1, '%.15f\n', pi);
分别直接等同于 short
和 long
对于 pi
但它们是否对于 eps
和 100.5
>> fprintf(1, '%.4f\n', eps);
0.0000
>> fprintf(1, '%.15f\n', eps);
0.000000000000000
>> fprintf(1, '%.4f\n', 100.5);
100.5000
>> fprintf(1, '%.15f\n', 100.5);
100.500000000000000
不 它们不是唯一的直接等价物是 fprintf(1, '%.4f\n', 100.5);
。如果我们尝试使用 %.g
会怎么样?
>> fprintf(1, '%.4g\n', eps);
2.22e-16
>> fprintf(1, '%.15g\n', eps);
2.22044604925031e-16
>> fprintf(1, '%.4g\n', 100.5);
100.5
>> fprintf(1, '%.15g\n', 100.5);
100.5
现在 fprintf
语句中的 none 直接等效。但是,我们可以使用
的 long
格式生成 eps
的直接等价物
>> fprintf(1, '%.16g\n', eps);
2.220446049250313e-16
因为%g
格式说明符.
后面的数字指定了有效数字的位数(包括小数点前的数字,.
)我们需要使用16 而不是 15.
要为 short
格式的所有这些输入类型生成直接等效项,我们需要混合 %.f
、%.g
和 %.e
说明符以及调整 field width.
>> format short
>> pi
ans =
3.1416
>> eps
ans =
2.2204e-16
>> 100.5
ans =
100.5000
>> fprintf(1, '%.4f\n', pi);
3.1416
>> fprintf(1, '%.5g\n', eps);
2.2204e-16
>> fprintf(1, '%.4f\n', 100.5);
100.5000
一点都不重要。 long
格式也可以这样做。
>> format long
>> pi
ans =
3.141592653589793
>> eps
ans =
2.220446049250313e-16
>> 100.5
ans =
1.005000000000000e+02
>> fprintf(1, '%.15f\n', pi);
3.141592653589793
>> fprintf(1, '%.16g\n', eps);
2.220446049250313e-16
>> fprintf(1, '%.15e\n', 100.5);
1.005000000000000e+02
甚至比 short
格式更糟糕。
简而言之,MATLAB 的 short
和 long
格式在 %d
、%.f
、%.g
和 %.e
说明符之间切换,具体取决于关于最合适的输入方法。
补充阅读
您可以通过 format
documentation. There is also a helpful document on Display Format for Numeric Values. And lastly, there is information about the Variable Editor and its preferences.
找到有关 MATLAB 中可用的不同显示格式的信息
在this question之后,我在看Matlab中double变量的精度。在那里,建议使用 fprintf
更仔细地查看变量。
奇怪的是Variable Editor和fprintf
显示的结果不一样,fprintf多显示一位。
% pi
Variable Editor: 3.141592653589793
fprintf('0.16f\n',pi): 3.1415926535897931
vpa('pi'): 3.1415926535897932384626433832795
% pi / 180
pi180 = pi/180
Variable Editor (pi180) 0.017453292519943
fprintf('%0.16f\n',pi180) 0.0174532925199433
vpa('pi/180') 0.017453292519943295769236907684886
在内部,Matlab 似乎正在处理由 fprintf
打印的精度>> fprintf('%0.16f\n',0.0174532925199433*10) % value from fprintf
0.1745329251994330
>> fprintf('%0.16f\n',0.017453292519943*10) % value from Variable Editor
0.1745329251994300
>> fprintf('%0.16f\n',pi180*10) % internal calculation
0.1745329251994330
为什么会这样?
如果我在函数中使用预先计算的 pi/180
,我应该使用来自 fprintf 还是来自变量编辑器的值?
tl;dr 在变量编辑器中,Matlab 在 15 位而不是 16 位处截断。
tl;dr MATLAB 中的变量使用双精度。命令 Window 和变量编辑器中的变量使用相同的精度。唯一的区别是显示格式和打印精度的小数位数。
默认情况下,MATLAB 对其变量使用双精度。 MATLAB 中的这些变量存储在工作区中。命令 Window 和变量编辑器都从同一个工作区中提取它们的变量,因此在下面使用相同的精度。
在变量编辑器和命令 Window 中显示变量的默认格式是 short
格式。您可以使用
>> get(0, 'format')
ans =
short
并通过转至 Preferences -> Variables -> Format
获取变量编辑器。默认情况下,short
格式将变量显示为精确到小数点后 4 位。
在我看来,您已将变量编辑器中变量的默认显示格式更改为 long
格式。此格式显示精度为 15 位小数的双精度变量。 long
和 short
格式都舍入变量,因此 pi
即 3.14159
被舍入为 3.1416
因为 9
在第 5 位小数short
格式显示时的位置
>> format short
>> pi
ans =
3.1416
这直接等同于fprintf
>> fprintf(1, '%.4f\n', pi);
3.1416
但是,long
格式,我猜,您已将变量编辑器设置为默认格式,四舍五入到小数点后 15 位,因此显示
>> format long
>> pi
ans =
3.141592653589793
直接等同于
>> fprintf(1, '%.15f\n', pi);
3.141592653589793
当您使用 fprintf(1, '%.16f\n', pi);
时,您将 pi
打印到小数点后 16 位,并且 而不是 15,这是由 long
格式指定的。这就是为什么你的输出是
>> fprintf(1, '%.16f\n', pi);
3.1415926535897931
注意,1
在这末尾。这就是为什么它前面的 3
在您的变量编辑器中显示时没有四舍五入为 4
的原因。
总结
- MATLAB 中的变量默认使用双精度
- MATLAB 变量存储在工作区
- 命令 Window 和变量编辑器中可用的变量均来自工作区并使用相同的精度
预先计算的值
在 MATLAB 中,您应该在函数调用或处理其他数值数据时使用变量名 pi180
。这将使用双精度并消除使用 fprintf
或变量编辑器输出的值可能出现的任何复制和粘贴错误。
fprintf
怪癖
tl;dr MATLAB 的 short
和 long
格式在 %d
、%.f
、[=49= 之间切换] 和 %.e
说明符取决于最合适的输入方法。
@horchler 指出 %.f
仅直接等同于特定输入的 short
和 long
格式,这是正确的。在 fprintf
和 MATLAB 的 short
和 long
格式之间,no 直接等效于 all 输入。
例如让我们看看 eps
和 100.5
并尝试打印与 MATLAB 的 short
和 long
格式完全相同的数字。
>> format short
>> eps
ans =
2.2204e-16
>> 100.5
ans =
100.5000
和
>> format long
>> eps
ans =
2.220446049250313e-16
>> 100.5
ans =
1.005000000000000e+02
现在我们从上面知道 fprintf(1, '%.4f\n', pi);
和 fprintf(1, '%.15f\n', pi);
分别直接等同于 short
和 long
对于 pi
但它们是否对于 eps
和 100.5
>> fprintf(1, '%.4f\n', eps);
0.0000
>> fprintf(1, '%.15f\n', eps);
0.000000000000000
>> fprintf(1, '%.4f\n', 100.5);
100.5000
>> fprintf(1, '%.15f\n', 100.5);
100.500000000000000
不 它们不是唯一的直接等价物是 fprintf(1, '%.4f\n', 100.5);
。如果我们尝试使用 %.g
会怎么样?
>> fprintf(1, '%.4g\n', eps);
2.22e-16
>> fprintf(1, '%.15g\n', eps);
2.22044604925031e-16
>> fprintf(1, '%.4g\n', 100.5);
100.5
>> fprintf(1, '%.15g\n', 100.5);
100.5
现在 fprintf
语句中的 none 直接等效。但是,我们可以使用
long
格式生成 eps
的直接等价物
>> fprintf(1, '%.16g\n', eps);
2.220446049250313e-16
因为%g
格式说明符.
后面的数字指定了有效数字的位数(包括小数点前的数字,.
)我们需要使用16 而不是 15.
要为 short
格式的所有这些输入类型生成直接等效项,我们需要混合 %.f
、%.g
和 %.e
说明符以及调整 field width.
>> format short
>> pi
ans =
3.1416
>> eps
ans =
2.2204e-16
>> 100.5
ans =
100.5000
>> fprintf(1, '%.4f\n', pi);
3.1416
>> fprintf(1, '%.5g\n', eps);
2.2204e-16
>> fprintf(1, '%.4f\n', 100.5);
100.5000
一点都不重要。 long
格式也可以这样做。
>> format long
>> pi
ans =
3.141592653589793
>> eps
ans =
2.220446049250313e-16
>> 100.5
ans =
1.005000000000000e+02
>> fprintf(1, '%.15f\n', pi);
3.141592653589793
>> fprintf(1, '%.16g\n', eps);
2.220446049250313e-16
>> fprintf(1, '%.15e\n', 100.5);
1.005000000000000e+02
甚至比 short
格式更糟糕。
简而言之,MATLAB 的 short
和 long
格式在 %d
、%.f
、%.g
和 %.e
说明符之间切换,具体取决于关于最合适的输入方法。
补充阅读
您可以通过 format
documentation. There is also a helpful document on Display Format for Numeric Values. And lastly, there is information about the Variable Editor and its preferences.