MATLAB 根据适用于双精度的 IEEE® 754 标准来构造双精度(即 double)数据类型。以 double 形式存储的任何值都需要 64 位,并按照下表所示进行格式化:
MATLAB 根据适用于单精度的 IEEE 754 标准来构造单精度(即 single)数据类型。以 single 形式存储的任何值都需要 32 位,并按照下表所示进行格式化:
由于 MATLAB 使用 32 位来存储 single 类型的数值,因此与使用 64 位的 double 类型的数值相比,前者需要的内存更少。但是,由于它们是使用较少的位存储的,因此 single 类型的数值所呈现的精度要低于 double 类型的数值。
一般使用双精度来存储大于 3.4 x 1038 或约小于 -3.4 x 1038 的值。对于位于这两个范围之间的数值,您可以使用双精度,也可以使用单精度,但单精度需要的内存更少。
由于 MATLAB 的默认数值类型为 double,因此您可以通过一个简单的赋值语句来创建 double 值:
x = 25.783;
whos 函数显示,MATLAB 已为您刚在 x 中存储的值创建了一个 double 类型的 1x1 数组:
whos x
Name Size Bytes Class
x 1x1 8 double
如果您只想验证 x 是否为浮点数,请使用 isfloat。如果输入为浮点数,此函数将返回逻辑值 1 (true),否则返回逻辑值 0 (false):
isfloat(x)
ans =
logical
1
您可以使用 MATLAB 函数 double 将其他数值数据、字符或字符串以及逻辑数据转换为双精度值。以下示例将有符号整数转换为双精度浮点数:
y = int64(-589324077574); % Create a 64-bit integer
x = double(y) % Convert to double
x =
-5.8932e+11
由于 MATLAB 默认情况下以 double 形式存储数值数据,因此您需要使用 single 转换函数来创建单精度数:
x = single(25.783);
whos 函数在结构体中返回变量 x 的属性。此结构体的 bytes 字段显示,当以 single 形式存储 x 时,该变量仅需要 4 字节,而以 double 形式存储则需要 8 字节:
xAttrib = whos(‘x’);
xAttrib.bytes
ans =
4
您可以使用 single 函数将其他数值数据、字符或字符串以及逻辑数据转换为单精度值。以下示例将有符号整数转换为单精度浮点数:
y = int64(-589324077574); % Create a 64-bit integer
x = single(y) % Convert to single
x =
single
-5.8932e+11
此部分介绍您可以在算术运算中将哪些类与浮点数一起使用。
您可以使用 double 和以下的任何其他类来执行基本算术运算。如果一个或多个操作数为整数(标量或数组),则 double 操作数必须为标量。运算结果默认为 double 类型,除非另有说明:
single - 结果为 single 类型
double
int* 或 uint* - 结果与整数操作数具有相同的数据类型
char
logical
以下示例对 char 和 double 类型的数据执行算术运算。结果为 double 类型:
c = ‘uppercase’ - 32;
class©
ans =
double
char©
ans =
UPPERCASE
您可以使用 single 和以下的任何其他类来执行基本算术运算。运算结果始终为 single:
single
double
char
logical
在以下示例中,7.5 默认为 double 类型,结果为 single 类型:
x = single([1.32 3.47 5.28]) .* 7.5;
class(x)
ans =
single
double 和 single 类都存在可以用该类型表示的最大数和最小数。
MATLAB 函数 realmax 和 realmin 分别返回可以用 double 数据类型表示的最大值和最小值:
str = ‘The range for double is:\n\t%g to %g and\n\t %g to %g’;
sprintf(str, -realmax, -realmin, realmin, realmax)
ans =
The range for double is:
-1.79769e+308 to -2.22507e-308 and
2.22507e-308 to 1.79769e+308
大于 realmax 或小于 -realmax 的数分别被赋予正无穷和负无穷值:
realmax + .0001e+308
ans =
Inf
-realmax - .0001e+308
ans =
-Inf
在用参数 ‘single’ 调用 MATLAB 函数 realmax 和 realmin 时,这两个函数会分别返回可以用 single 数据类型表示的最大值和最小值:
str = ‘The range for single is:\n\t%g to %g and\n\t %g to %g’;
sprintf(str, -realmax(‘single’), -realmin(‘single’), …
realmin(‘single’), realmax(‘single’))
ans =
The range for single is:
-3.40282e+38 to -1.17549e-38 and
1.17549e-38 to 3.40282e+38
大于 realmax(‘single’) 或小于 -realmax(‘single’) 的数分别被赋予正无穷和负无穷值:
realmax(‘single’) + .0001e+038
ans =
single
Inf
-realmax(‘single’) - .0001e+038
ans =
single
-Inf
如果浮点算术计算的结果不如预期的精确,可能是由于您的计算机硬件的限制所致。由于硬件缺乏足够的位而无法呈现具有完美精度的结果,计算机可能会将结果值截断,使得结果值不够准确。
由于双精度数的数量有限,因此您无法在双精度存储中表示所有数值。在任何计算机上,每个双精度数和下一个更大的双精度数之间都存在一个较小的间隔。您可以使用 eps 函数确定此间隔的大小,该大小限制了您的结果的精度。例如,要计算 5 和下一个更大的双精度数之间的间距,请输入
format long
eps(5)
ans =
8.881784197001252e-16
这表明,5 和 5 + eps(5) 之间不存在任何双精度数。如果某个双精度计算返回答案 5,则结果仅精确到 eps(5) 之内。
eps(x) 的值取决于 x。以下示例显示,当 x 变得更大时,eps(x) 也会变得更大:
eps(50)
ans =
7.105427357601002e-15
如果您输入不带输入参数的 eps,MATLAB 将返回 eps(1) 的值(从 1 到下一个更大的双精度数之间的间距)。
同样,两个单精度数之间也存在间隔。如果 x 的类型为 single,则 eps(x) 返回 x 和下一个更大的单精度数之间的间距。例如,
x = single(5);
eps(x)
返回
ans =
single
4.7684e-07
请注意,此结果大于 eps(5)。由于单精度数的数量少于双精度数的数量,因此单精度数之间的间隔也大于双精度数之间的间隔。这意味着,单精度算术运算的结果精度要低于双精度算术运算的结果精度。
对于类型为 double 的双精度数 x,eps(single(x)) 的计算值即为将 x 从 double 转换为 single 时的舍入上限。例如,当您将双精度数 3.14 转换为 single 时,它会通过以下方式进行舍入
double(single(3.14) - 3.14)
ans =
1.0490e-07
3.14 舍入的数量小于
eps(single(3.14))
ans =
single
2.3842e-07
MATLAB 中几乎所有运算都是通过符合 IEEE 754 标准的双精度算术运算执行的。由于计算机仅将数值表示为有限精度(双精度需要 52 个尾数位),因此计算有时会生成数学上的非预期结果。务必注意,这些结果并非 MATLAB 中的错误。
使用以下示例来帮助您确定这些情况:
十进制数 4/3 不能精确表示为二进制分数。为此,以下计算的结果不是零,而是显示数量 eps。
e = 1 - 3*(4/3 - 1)
e =
2.2204e-16
同样,0.1 也不能精确表示为二进制数。因此,您会发现以下非预期行为:
a = 0.0;
for i = 1:10
a = a + 0.1;
end
a == 1
ans =
logical
0
请注意,计算中运算的顺序会很重要:
b = 1e-16 + 1 - 1e-16;
c = 1e-16 - 1e-16 + 1;
b == c
ans =
logical
0
浮点数之间存在间隔。当数值变得越大时,间隔也会变得越大,如以下所示:
(2^53 + 1) - 2^53
ans =
0
由于 pi 实际上不是 π,因此 sin(pi) 不精确为零并不足为奇:
sin(pi)
ans =
1.224646799147353e-16
对几乎相等的操作数执行减法时,有时可能会发生意外取消。以下是因淹没(使加法没有意义的精度损失)导致的取消的示例。
sqrt(1e-16 + 1) - 1
ans =
0
MATLAB 中的某些函数(例如 expm1 和 log1p)可用于弥补这种灾难性取消所造成的影响。
解决线性代数的问题时,舍入、取消和浮点算术运算的其他一些特性结合起来时,可能产生令人意想不到的运算。MATLAB 会警告下面的矩阵 A 是病态的,因此即便是细微的扰动,都可能对方程组 Ax = b 产生很大的影响:
A = diag([2 eps]);
b = [2; eps];
y = A\b;
Warning: Matrix is close to singular or badly scaled.
Results may be inaccurate. RCOND = 1.110223e-16.
这些只是几个例子,用于说明 IEEE 浮点算术运算如何影响 MATLAB 中的计算。请注意,IEEE 754 算术运算中执行的所有计算都会受到影响,这包括用 C 或 FORTRAN 编写的应用程序以及 MATLAB。
该博文为原创文章,未经博主同意不得转。
本文章博客地址:https://cplusplus.blog.csdn.net/article/details/127794078