打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
11. matlab常见的语法错误、逻辑错误与舍入误差

错误和陷阱

这一章你将开始认识和避免各种错误和陷阱。

即使是有经验的程序员,第一次能够让程序正确运行的情况也很少见。在计算机术语中,程序中的错误被称为bug。有一个故事说,早期的计算机中发生了一个不幸的事故,一只蛾子短路了两个热电子管。这个原始(被烧焦的)“bug”花了几天时间才找到。因此,检测和纠正这些错误的过程被称为debugging(调试)。在MATLAB中会出现一些特定的错误和陷阱,也会出现在任何编程语言中的一些错误和陷阱。这些问题在本章中会简要讨论。

11.1 语法错误

语法错误是在MATLAB语句中出现的打字错误(例如,plog而不是plot)。它们是最常见的错误类型,并且是致命的:MATLAB停止执行并显示错误消息。随着MATLAB从一个版本演变到另一个版本,错误消息得到改进。请尝试下面的示例来检查最新的错误消息:

2*(1+3
disp(['the answer is ' num2str(2)]

上述示例中有许多可能的语法错误,也许您也已经发现了其中一些。通过经验,您将更善于发现自己的错误。

函数lasterr返回最近生成的错误消息。可以通过调用lasterr函数来获取最近的错误消息,如下所示:

errorMsg = lasterr;
disp(errorMsg);

这将打印出最近生成的错误消息。

请注意,MATLAB的不同版本之间的错误消息可能会有所不同,因此随着MATLAB版本的更新,检查最新的错误消息可以帮助您更好地理解和调试代码中的语法错误。

11.1.1 矢量大小不兼容

表示在MATLAB中进行向量操作时遇到了不兼容的向量大小。

在MATLAB中,许多函数和操作都期望输入的向量具有相同的大小或符合一定的尺寸规则。如果向量的大小不兼容(例如,两个向量的长度不一致),就会出现"Incompatible vector sizes"错误。

下面是一些可能导致这种错误的常见情况:

  1. 向量长度不一致:例如,当尝试对长度不同的向量执行向量运算(如加法、乘法等)时,就会出现这个错误。
A = [1 2 3];
B = [4 5];
C = A + B; % Incompatible vector sizes error
  1. 矩阵维度不匹配:当对矩阵进行操作时,涉及的行数和列数也必须匹配,否则可能导致不兼容的向量大小错误。
A = [1 23 4];
B = [5 6 78 9 10];
C = A * B; % Incompatible matrix dimensions error
  1. 函数的输入参数尺寸不匹配:当使用需要相同大小的向量作为输入参数的函数时,如果向量的尺寸不匹配,就会出现该错误。
x = 1:10;
y = 5:20;
z = linspace(01100);
plot(x, y); % Incompatible vector sizes error
plot(x, z); % Incompatible vector sizes error

解决"Incompatible vector sizes"错误的方法通常涉及检查向量的大小,并确保它们满足所需的尺寸规则。可以使用函数sizelength来检查向量的大小,并根据需要采取适当的操作(例如重新定义向量的大小、截取相同的子集等)。


比如下面这段代码会出现问题:

x = 0:pi/20:3*pi;
y = sin(x);
x = 0:pi/40:3*pi;
plot(x,y)

因为你忘了在减少 x 的增量后重新计算 y。Whos揭示了问题所在:

在给定的示例中,我们首先定义了一个向量x,以及根据x计算得到的另一个向量y。然后,我们重新定义了x,使用了更小的增量。接下来,我们试图使用重新定义的x和原先的y进行绘图。这就是导致错误消息"Vectors must be the same lengths(向量长度必须相同。)"的原因,因为xy的长度不匹配。

在这个例子中,我们可以通过在重新定义x之后重新计算y来解决问题,以确保xy具有相同的长度。以下是修正后的代码示例:

x = 0:pi/20:3*pi;
y = sin(x);
x = 0:pi/40:3*pi;
y = sin(x); % 重新计算y以匹配新的x长度
plot(x, y);

通过在重新定义x之后重新计算y,我们确保了xy具有相同的长度。现在,我们可以使用它们来进行绘图,而不会出现长度不匹配的错误。

在使用MATLAB进行向量操作时,始终确保相关的向量具有相同的长度或尺寸,这是防止出现"Vectors must be the same lengths(向量长度必须相同。)"错误的关键。使用whos命令可以查看变量的尺寸和类型,有助于发现和解决类似问题。

11.1.2 名称隐藏

名称隐藏是指在MATLAB中存在具有相同名称的不同变量或函数时,较新定义的变量或函数会隐藏较旧定义的变量或函数。这意味着在同一作用域内,较早定义的实体将无法被访问。

当存在名称隐藏时,MATLAB将优先使用最近定义的变量或函数。这可能会导致程序行为与预期不符,特别是当我们意外地在同一作用域内使用了相同名称的变量或函数时。

以下是一个示例,说明名称隐藏是如何发生的:

x = 10;  % 定义一个变量x并赋值为10
disp(x); % 输出结果为10

x = 20;  % 重新定义变量x并赋值为20
disp(x); % 输出结果为20

% 在此处新定义一个变量x
x = 30;  % 定义了一个新的变量x并赋值为30
disp(x); % 输出结果为30

在此示例中,最后一个定义的变量x会隐藏之前定义的变量x。因此,在第二个disp(x)语句中,输出结果为20,而不是使用最早定义的变量x的数值10。

名称隐藏可以在不同的作用域中发生。例如,在函数中定义的变量或函数参数会隐藏同名的全局变量。在这种情况下,该函数将优先使用局部变量,而不会访问全局变量。

为了避免名称隐藏问题,我们应该为不同的变量和函数选择不同的名称,以避免产生混淆和错误。如果真的需要在同一作用域中使用相同的名称,可以考虑使用结构体或不同的命名空间来区分它们,并确保在使用这些变量或函数时进行明确的引用。

回顾一下,工作区中的变量“隐藏”了与其同名的脚本或函数。要访问这样的脚本或函数,唯一的方法是从工作区中清除具有相同名称的变量。此外,MATLAB函数也会隐藏具有相同名称的脚本。例如,创建一个名为why.m的脚本,其中显示一些无关消息,然后在命令行中输入why。

如果你担心你要创建的变量或脚本(比如blob)可能是MATLAB函数,可以先尝试使用help blob来查看帮助文档。

11.2逻辑错误

逻辑错误是在程序中出现的错误,不是由语法错误引起的。它们是最难调试和发现的错误类型,因为程序可以正确运行并且没有错误消息,但结果却与我们预期的不符。

逻辑错误通常发生在程序的算法或逻辑推理方面。这可能是由于错误的条件判断、错误的计算或错误的流程控制引起的。逻辑错误不会导致程序崩溃或错误消息的显示,但会导致程序输出的结果不正确。

调试逻辑错误通常需要仔细检查代码,并使用调试技术,如打印中间结果、使用断点、追踪代码执行流程等。重点是思考程序的预期行为和实际行为之间的差异,并审查相关的算法和逻辑推理。同时,编写清晰、模块化、可测试的代码也是减少逻辑错误并更容易进行调试和维护的关键。尽量遵循良好的编码实践和使用适当的测试方法来减少逻辑错误的发生。

以下提示可能能帮助你检查逻辑。

  • 尝试在一些你已知答案的特殊情况下运行程序。
  • 如果你不知道任何确切的答案,尝试根据对问题的洞察力来检查答案是否似乎在正确的数量级上。
  • 尝试手动运行程序(或使用MATLAB的出色的交互式调试工具),看看哪里开始出错。

11.3 舍入误差

舍入误差是在进行浮点数计算时,由于计算机的有限精度表示而引起的误差。计算机使用二进制来表示浮点数,但大多数十进制数无法精确地表示为有限的二进制数。因此,在进行浮点数计算时会引入一些近似误差。

舍入误差主要有两个来源:

  1. 尾数截断:由于计算机使用有限的位数来表示浮点数的尾数部分,当需要表示一个无限位数的十进制数时,尾数截断会导致近似误差。这意味着浮点数的表示只能保留有限位数的有效数字,导致精度丢失。

    例如,考虑下面的计算:

   0.1 + 0.2

在十进制中,这个计算应该得到0.3作为结果。但是,当使用浮点数进行计算时,可能会得到一个近似值,例如:

   0.1 + 0.2 = 0.30000000000000004
  1. 运算顺序:当进行多个浮点数计算时,并且这些计算的顺序不当,也会导致舍入误差的累积。

考虑以下示例:

    a = 0.1 + 0.2;    % 得到一个近似结果
    b = a - 0.3;      % 得到一个近似结果
    disp(b);

在上述代码中,我们本来希望得到0,因为0.1 + 0.2 - 0.3 应该等于0。然而,由于中间结果的近似性,可能会得到一个不为0的结果,例如:

b = -2.7755575615628914e-17

这是由于先计算的 0.1 + 0.2 结果的舍入误差,再减去 0.3 时产生了累积误差。

为了最小化舍入误差的影响,可以考虑以下几点:

  • 避免对浮点数进行比较,特别是使用等于运算符(==)进行比较。由于舍入误差的存在,两个看似相等的浮点数可能不会被判定为相等。代替地,可以使用范围比较或近似判断。

  • 提高运算精度:在某些情况下,可以使用具有更高精度的数值库或工具来进行计算,以减少舍入误差的影响。

  • 了解和理解浮点数处理的规则:熟悉浮点数表示和计算中的规则和限制,可以帮助更好地预测和处理舍入误差。

  • 调整计算的顺序:在进行多个浮点数计算时,调整计算顺序以减少舍入误差的累积效应,可以改善结果的精度。


在计算机上进行浮点数计算时,由于有限的精度表示,舍入误差可能导致程序给出我们知道是错误的数值答案。这是因为计算机在表示浮点数时只有有限的字节,而不是无限位数。

对于给定的程序代码:

x = 0.1;
while x ~= 0.2
    x = x + 0.001;
    fprintf('%g %g\n', x, x - 0.2)
end

你会发现,你需要通过中断程序(在PC上使用Ctrl-Break)才能停止它。变量x永远不会完全等于0.2,这是由于舍入误差导致的。事实上,x相对于0.2而言约差个8.3 × 10^(-17),这可以从显示x - 0.2的值得出。因此,使用不等于操作符~=来比较两个浮点数可能是不可靠的。

为了解决这个问题,一种更好的方法是使用一个小的误差范围进行比较。例如,可以将while循环的条件改为while x <= 0.2,或者更好地改为while abs(x - 0.2) > 1e-6。这样做会允许x在一定的误差范围内与0.2进行比较。

在一般情况下,更好的做法是使用相对误差进行两个非整数表达式之间的“相等”测试,如下所示:

if abs((a - b) / a) < 1e-6
    disp('a practically equals b');
end

或者

if abs((a - b) / b) < 1e-6
    ...

请注意,这种等式测试是基于a和b之间的相对差异,而不是绝对差异。相对误差测试能够更好地处理不同数量级的数值,以及避免舍入误差导致的问题。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
MATLAB主要命令汇总 -- 爱数学 -- 编程爱好者博客
Matlab命令汇总(2)
MATLAB命令大全(一)
IEEE 754 浮点数的表示精度探讨
使用浮点数和小数中的技巧和陷阱
你不知道的Python特性,其实可以解决很多问题!
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服