This chapter covers the most essential and widely used programming tools, operators, and control statements in MATLAB. In addition, the chapter covers modeling essentials in Simulink, the development of a graphical user interface (GUI), and the development of MATLAB executable files and stand-alone applications. Also, the chapter shows a number of simple examples demonstrating efficient ways to program and model in MATLAB/Simulink to save computation time as well as how to create short and compact code/scripts. In the process, I will give a few essential hints and show different approaches for writing robust programs and scripts. Throughout the book, key terms such as script, code, program, M-file, MLX-file, and function file are used frequently to refer to the programs written for MATLAB. The script and M/MLX-files, including the function files, are meant to be source code readable by users, not the machine code understood by a computer.

Writing M/MLX-Files

The previous chapter discussed various entries, such as arrays, characters, cells, structures, tables, and logic arrays, via examples in the Command window. Also, I gave a general overview of M/MLX-file editors by writing several short pieces of code (scripts) that performed computations. Scripts (M/MLX-files) can also be written in Notepad or WordPad. They become M-files as soon as they are named with a file extension of *.m or *.mlx.

As discussed in the previous chapter, the M/MLX-file editors have many easy-to-use tools and some easy-to-understand options that can be employed while writing and debugging scripts. The M/MLX-file editors’ most used tools are the ability to use cell modes, set up breakpoints, evaluate selected lines of cells or scripts, use automatic error detection options for misspelled command names and missing brackets in algebraic operations, detect all used and unused/unreferred to but introduced variables, and get useful hints to improve the script performance and display of warning hints on unnecessarily assigned variables, see the overloaded display of results, use variable values within loops, use a profile viewer, and so forth.

All of these tools of the M/MLX-file editors help you avoid syntax errors while writing scripts. In addition, there are many other tools that help you save time and effort on the mechanical parts such as writing reports and publishing reports in HTML or PDF formats, for example.

Before starting to write some code, let’s consider the most essential steps in any programming language. The process of writing code starts with a pen and paper and is composed of the steps shown in Figure 2-1.

Figure 2-1
A flowchart of the process of writing code. The flow starts with create input variables and ends with yes after the quality is achieved.

General process of code/program writing

This flowchart shows the following steps:

  1. 1)

    Clarify the problem statement.

  2. 2)

    Clarify/create/declare input variables: var1, var2, var3 ... varN.

  3. 3)

    Read the values of var1, var2, var3, ... , varN.

  4. 4)

    Define the output variables: out1, out2, out3, ... outN. Perform computation, evaluation, and analysis operations.

  5. 5)

    Check the quality/correctness of the obtained results/output variables.

  6. 6)

    If the quality/correctness of the achieved results is not adequate, then go back to step 3. Repeat steps 3 through 5 until the expected quality/correctness is attained.

  7. 7)

    End and report on the results.

This algorithm is a generalized process and might also include considering objectives, specifics, and nuances, such as input/output data types, sources, evaluation/computation operations, etc. Once the (general) algorithm is well-defined, you can begin coding in the given programming language. When writing code, the most time- and effort-consuming part is to carry out the verification operations in steps 3 to 5. This is called debugging, and it helps you locate errors or flaws in the calculation/evaluation and analysis operations from step 4.

Specifically, debugging is the process of correcting the syntax of the code, script, or program with respect to the programming language, correcting the calculation/computation operations with respect to the given problem statement, and, if required, adjusting the precision of the output. Debugging is not so straightforward in many instances, but MATLAB’s M/MLX file editors have a few helpful tools that detect general errors made in your scripts. At the same time, many errors cannot be detected without executing and analyzing the obtained outputs. There is no single solution approach to finding all possible bugs (flaws and mistakes) made when writing code. One of the most common ways to see if the code is performing as anticipated is to use test examples and then verify the output.

Throughout the book, considerable attention is given to debugging. It must be noted that it is impossible to write code without any flaws. Therefore, debugging is a “must-have” step. Moreover, you will hone your programming skills when you write code that solves different problems and make errors that you can then find and fix.

Note

Always start writing your scripts with simple operations/commands to perform the most essential parts of the exercise. Once the essential parts of the exercise are complete, you can add more details. It’s good programming practice to move from the simple to the complex.

How to Create an M/MLX-File

There are a few ways to create a new script (in this case, an M/MLX-file).

  1. 1)

    By typing >> edit in the Command window and pressing the Enter key on the keyboard.

  2. 2)

    By hitting Ctrl+N on the keyboard.

  3. 3)

    By clicking for the M-file.

  4. 4)

    By clicking for the MLX-file.

  5. 5)

    By clicking and selecting from the drop-down options for the M-file or for the MLX-file or for a function file with an *.m file extension or for a function file with an *.mlx file extension

  6. 6)

    By collecting the commands typed in the Command window via these commands: diary on, diary NewFileName, diary off

Warnings in Scripts

While writing M/MLX-files, including the function files, the M-file and MLX (Live)-file, editors automatically generate some warning signs that are in many instances very helpful hints to improve the efficiency of scripts and locate some missing or overlooked arguments. They do not prevent the scripts from being executed, though. These warnings are indicated by underlined wavy lines and hyphens and rectangular boxes on the right side of the M-file Editor window. They are by default orange. Similarly, the MLX-editor (Live Editor) indicates warnings by underlined wavy lines, as well as hyphens and triangular warning signs on the right-side bar of the Editor window. Note that their color type can be adjusted via the Preferences settings. There are a few common warnings that are detected automatically by the M/MLX-file editors. They are as follows:

  • To suppress the display of outputs in the Command window detected by the M-file editor only.

A screenshot of a 5-line code with a warning message, that reads, terminate statement with semicolon to suppress output is highlighted on the bottom and has details and fix buttons.
  • To suggest memory allocation (e.g., the variables A and B are underlined with an orange wave line) when a variable size changes/increases in the loop iteration within [for ... end] and [while ... end].

A screenshot of a command window. Line 1 reads warnings with memory allocation. A warning message with a drop-down button labeled details is highlighted at the bottom.
A screenshot of a command window. Line 1 reads warnings with memory allocation. A warning message with a drop-down button labeled details is highlighted at the bottom.
  • To cancel the premature ending of the command with comma. For example, the comma after the grid on the command (on line 4) needs to be replaced with a semicolon.

A screenshot of a command window. Line 1 reads warnings with premature ending and has a warning dialog box with an explanation and suggested action at the bottom.
  • To remove unnecessary semicolons. For example, at the end of line 1, the ; is unnecessary.

A screenshot of a 4-line code. A warning message for unnecessary semicolon usage in the function statement before a newline has popped up in the center.
  • To remove unnecessary semicolons in the [for ... end] loop’s index declaration (on line 4).

A screenshot of a 9-line code. A warning message for unnecessary semicolon usage in the F O R statement before a newline has popped up in the center.
  • To indicate unused but assigned variable names (G on line 5) within M-files.

A screenshot of a command window. Line 1 reads warning on unused variable. It has a warning message for the same at the bottom with a drop-down arrow labeled details.
  • To indicate missing arguments when formatting fprintf().

A screenshot of a 6-line code. Line 1 reads warnings on missing arguments. A warning message on the bottom highlights the same.
  • To indicate unnecessary brackets (a = [13] on line 2).

A screenshot of a command window. Line 1 reads a warning on unnecessary brackets. A warning message on the bottom says the use of brackets is unnecessary.
  • To indicate an unrecommended function. For example, xlswrite() on line 2 is not recommended; instead, it is recommended to use writematrix() or writecell(). Note that the unrecommended function detecting warning option is available starting from the MATLAB R2022a version.

A screenshot of a 4-line code. Line 1 reads warnings with unrecommended function use. A warning message at the bottom highlights the same.

It must be noted that some of the warning signs detected by the M-file editor will not be picked up by MLX-editor (Live Editor). For example, the missed ; used to suppress the display of the output in the Command window is not applicable to the MLX-editor (Live Editor).

On the other hand, other warnings such memory allocation warnings, unnecessary semicolons, missing arguments when formatting fprintf( )d, and unnecessary brackets are detected and highlighted very explicitly with the MLX-editor with an icon on the right side of the Editor window.

  • To advise the memory allocation.

A screenshot of a 5-line code. Line 1 reads warnings with memory allocation. A warning text on the bottom reminds to change the size of a variable.
  • To indicate the prematurely ended command with a comma.

A screenshot of a 4-line code. Line 1 reads warnings with unrecommended function use. A warning text highlights the wrong usage of a comma in line 4.
  • To indicate unnecessary semicolons in the function statement.

A screenshot of a 6-line code. A semicolon in line 1 is highlighted with a warning text that says it is unnecessary in the function statement.
  • To indicate unnecessary semicolons in defining indexes for the [for ... end] loop.

A screenshot of an 8-line code starts with warnings with an unnecessary semicolon. A semicolon is highlighted in line 4 with a warning text for the same.
  • To indicate a missing argument in fprintf().

A screenshot of a 6-line code starts with warnings on missing arguments in formatting. The command on line 6 is highlighted with a warning text for the same.
  • To indicate unnecessary bracket.

A screenshot of a 2-line code starts with a warning on unnecessary brackets. A warning text on the bottom says the use of brackets is unnecessary.
  • To indicate an unrecommended function use. For example, xlswrite() on line 2 is not recommended. Instead, it is recommended to use writematrix() or writecell(). Note that the unrecommended function detecting warning option is available starting only from the MATLAB R2022a version.

A screenshot of a 4-line code starts with warnings with unrecommended function use. A warning text for the same highlights the xlswrite command in line 4.

Errors in Scripts

In MATLAB, scripts can contain code to perform various computations and analyses and to define functions. Let’s look at a few simple examples of how to write scripts in the M-file and MLX-file editors and see how to locate/fix common errors occurring while writing scripts.

Example 1

Let’s solve a quadratic equation represented in a general form: ax2 + bx + c = 0. First, open an M-file editor and type in the following commands:

a=input('Enter, a = '); b=input('Enter, b = '); c=input('Enter, c = '); D=b^2-4*a*c; disp(['Discriminant of the equation is: ' num2str(D)])

Once the file is saved with a file extension of *.m, then it can be executed. When it is executed, this code prompts the user for three input (input()) entries and then computes the discriminant of the quadratic equation with the user entries for a, b, and c and displays the result in the Command window. It should be noted that the command disp() on line 5 is optional and is used to display the computation result in the Command window with some comments. The command disp() does not make any changes in the output. There are two more computing steps left in this code, namely, computing the two roots of the quadratic equation. The remaining steps can be inserted after line 5. If there are some illegal operations/errors while writing the script, the M/MLX-file editor will automatically detect them and underline them with red waves.

A screenshot of a 7-line code. The three error buttons on the right margin are annotated.

There is one error on line 6 (the red wavy line under a), where the multiplication sign is missing, and one warning shown with an orange wavy line under the = sign on line 7, where a semicolon (;) is recommended to suppress the display of the output from this line.

Error and warning messages like the ones on lines 6 and 7 with red and orange highlights are shown on the right edge of the editor’s scroll bar. If there is a red wavy line showing errors, the script (M/MLX-file) cannot be executed. If there are any warning signs with orange wavy underlines, that script can be executed without a problem. A few different types of typos or illegal operations are detected automatically by the M/MLX editors, but they cannot be fixed automatically. Thus, you have to understand and work out such issues.

A screenshot of a 6-line code. An error message on the bottom says parse error at a colon usage might be invalid M A T L A B syntax.

The warning message on line 7 can be fixed either by putting a semicolon where the cursor is or by clicking the Fix button.

A screenshot of a 7-line code with a warning message. The fix button on the right edge of the warning message is annotated.

Finally, here is the fixed script. The green square in the right corner indicates that the syntax of all the typed-in commands are correct, and the script is ready for execution.

A screenshot of a 7-line code. The top-right corner has a square symbol.

C

Now after saving this script with a file name of Eqn.m, it can be executed by clicking the button on the Editor’s main menu, by pressing Ctrl+Enter on the keyboard, or by calling the script by its name (>> run('Eqn')) from the Command window directly. Another way of executing the code is pressing the F5 functional key on the keyboard. After executing it, it prompts for the input in the Command window. You would enter the values 1, 2, and 3 for a, b, and c, respectively.

Enter, a = 1 Enter, b = 2 Enter, c = 3 Discriminant of the equation is: -8

Then the whole computation is completed, and this is what is obtained in the Command window. There are also some other variables saved in the Workspace window that are shown.

A screenshot of a window titled workspace. The left pane has a listicle for names and the right pane has a listicle for values.

All of the entries and processed/computed outputs from the scripts and M/MLX-files are saved automatically in the workspace. Except for when the function files are executed, not all results are saved in the workspace apart from the specified output variables in the function file. This issue will be addressed in the Function Files section of this chapter.

Example 2

Compute the following expression by writing an M-file (script): \( ab\ \sqrt[3]{\frac{{\left( ax- by\right)}^2}{cd-f}} \), where \( x=\left[\frac{1}{5},\frac{2}{5},\frac{3}{5},\frac{4}{5}\right],\kern0.5em y=\left[\frac{1}{3},\frac{2}{3},1,\frac{4}{3}\right],c=2,d=2.5,\textrm{and}\ f=2 \) and the values a, b with the user entries (scalars). According to the given values of the variables, x and y are row arrays and the other variables (a, b, c, d, f) are scalars.

Like with the quadratic equation, the input prompts are included in the script.

A screenshot of a 9-line code. A warning message on the bottom says invalid syntax. The two error buttons on the right pane are annotated.

This is the created short script to compute the given assignment. By taking a quick look at this script, you can see that there is one error detected by the MATLAB editor. It is invalid syntax related to a missing parenthesis at the end of line 9 that is true, and in fact, the missing parenthesis is before the first power raise (^) sign. Here is the fixed code with the green square in the upper-right corner:

A screenshot of a 9-line code starts with an example colon simple calculation. The top right corner has a square button, which is annotated.

Now everything appears to be correct according to the editor syntax. However, there are still several errors.

  • On line 4 while defining the elements of x, a semicolon is used as an element separator that must be a comma or just a space.

  • The variable f is defined on line 8, but in the expression on line 9 ff is used instead.

  • The computation expression on line 9 is performed with the variables a, b, c, d, and f, which are scalars, and the variables x and y, which are row arrays. That is not correct. This line has to contain element-wise operations over the row array variables x and y. After fixing these errors, the script will be in the following form:

A screenshot of a 9-line code. Line 1 reads, example colon simple calculation. It has a square button on the top right corner.

Now the script can be executed by pressing Ctrl+Enter or F5 on the keyboard without saving it or by clicking after saving it. Here are the results (input entries from the Command window):

Enter, a = 1 Enter, b = 2R

Here are the variables in the workspace:

A screenshot of a window titled workspace. The left pane has a listicle for names. The right pane has a listicle for values.

Example 3

Let’s compute the mathematical expression’s values and plot them by using the MLX-file editor and creating the MLX-file. Given: H(t) = sinsin (ωt); ω = 3; t = [00, 4500] with ∆t = 10.

Note that the given argument values of t are in degrees, not in radians. In MATLAB there are two functions, namely, sin() and sind(), to compute sine function values with input arguments in radians and degrees, respectively. Therefore, in such cases, there are two approaches: one should always use the right MATLAB function or one should employ the conversion function from degrees to radians (deg2rad()) or vice versa (rad2deg()).

Now the MLX-file (script) is created in a live editor by considering the input argument t:

A cropped screenshot of a command with a pop-up tab titled angle in degrees. The first option omega is highlighted.
A screenshot of the command window depicts a warning text at the bottom. The two error icons on the right pane are annotated.

Note that the error is shown by the wavy underline, and and in red on the right side of the MLX-editor. After fixing the error (the comma before *), the corrected code will be in the following form:

A cropped screenshot of a command window with a pop-up tab titled angle in degrees and option t is highlighted in it.

There are several essential differences between the M-file editor and MLX-file editor. One of them is that the MLX-editor can detect automatically the previously defined variables after typing the first letter of the variable name as an input argument with an additional hint showing the argument type to be inserted (e.g., t is the angle in degrees). Another feature of the MLX-file editor is that it does not show a warning message if the semicolon is not placed at the end of commands assigning variable values. For example, t = 0:1:450, which we saw while working with the M-file editor. The MLX-file editor displays the outputs not in the Command window but in the MLX-editor’s right-side window. At the same time, all of the variable values and computed expression values are saved in the workspace after executing the MLX-files just like with the M-files. The execution of the MLX-files is similar to M-files that can be done by pressing Ctrl+Enter on the keyboard or by clicking the button. Here is the final script with the plot() command and its computed results:

A screenshot of the command window. The left pane has commands written on it. The right pane has a graph for H of t versus t that plots continuous sine curves.

Example 4

Write an MLX-file that analyzes and computes the following acceleration equation a(v) (acceleration as a function of velocity) of a skydiver:

$$ a(v)=g\left(1-\frac{v^2}{3600}\right) $$
$$ g=9.81\ \frac{m}{s^2} $$
  1. 1.

    Plot a versus v.

  2. 2.

    Compute the terminal speed of a skydiver when \( a(v)\cong 0\frac{m}{s^2} \).

  3. 3.

    Take the vertical velocity v to be independent variable with the step size of \( \Delta v=0.1\frac{m}{s} \) within \( \left[0,\kern0.5em 100\frac{m}{s}\right]. \)

  4. 4.

    Display the terminal speed value on the plot.

Here is the initial code with one error on line 8 because of a mistyped variable name (Ttt instead of Tt), indicated by the exclamation point icon. This type of error (a mistyped variable name) can be detected in the live editor only after executing the script, not while writing it.

A screenshot of a command window. The left pane has commands. The right pane has a graph for acceleration versus velocity with a concave down decreasing curve. Warning icons are annotated.

Note that the error with the mistyped variable name (Ttt instead of Tt) showed up after executing the MLX-file editor. The results of calculations from the MLX-editor, unlike the M-file editor, do not show up in the Command window. Therefore, it is a good idea to execute the live script frequently to catch any overlooked rules and errors while typing and editing the scripts in the MLX-editor.

Here are the corrected and final solution scripts for this exercise in the MLX-editor:

A screenshot of a command window. The right pane has a graph for acceleration versus velocity that plots a concave down decreasing curve, while the left pane has commands.

The outputs are displayed within the same window on the right side, including the plot figures. In this exercise, there are a few lines of (nonexecutable) text; comments and equations are added between executable commands by using the and equation editor GUI tools of the MLX-editor, which are not available in M-file editor.

Example 5

It is possible to call within an M-file another M/MLX file or files. Let’s look at an example of writing M- and MLX files to compute the following expressions. You’ll also obtain their computation results by calling/executing another M/MLX-file. This will demonstrate how you link/connect several scripts (M/MLX files) or, in other words, how you execute several scripts, obtain their simulation results, and use them within a single script.

  1. 1)

    Compute F(α) = esin(α); H(β) = ecos(β)S = 1 − (sin2α + cos2 β); for α =  − 2π...2π; β =  − 3600...3600 by writing an MLX-file.

  2. 2)

    Compute (at) − sin sin (bt), for a = 3, b = 2, −13 ≤ t ≤  − 3 with ∆t = π/50 by writing an M-file.

  3. 3)

    Compute f (t) = cos cos (20t) −  sin (10t), for t ∈ [−π,  π] with ∆t = π/50 , and plot the computation results t versus f(t) by writing an M-file.

  4. 4)

    Compute \( T(s)=\frac{13{e}^{-2s}}{s^2+\delta {\omega}_ns+{\omega}_n^2\ } \) for δ = [0,  0.5,  1,  1.5, 2]; \( {\omega}_n=3\left[\frac{rad}{\mathit{\sec}}\right];s=\left[0,25\right],\Delta s=5\ast {10}^{-2} \) by writing MLX-file.

  5. 5)

    Write an M-file that executes all of the M and MLX-files from the previous tasks and saves all the computation results in a single array called A1 (for step 1), a table array called Btab2 (for step 2), a cell array called Ccell3 (for step 3), and a structure array called Dstruct4 (for step 4).

Here are the solution scripts in the M/MLX-files of these five tasks.

This MLX-file, called ET1.mlx, is the solution of task 1:

A screenshot of an M L X file for computation. Values are assigned to variables on the top. The bottom has a 2-line command written on it.

At initial glance, this script (ET1.mlx) looks error-free, and the MLX editor does not show any problematic issues. However, there are two errors (in array power operations) on line 2 in computing S, which will be detected by the editor only after you execute the script.

A screenshot of an M L X file for computation. The error icons on either margin of the window are annotated.
A cropped screenshot depicts an error message for error using superscript symbol.

Here is the corrected script:

A screenshot of the corrected script in a command window for computation. Values are assigned on the top and a two-line command is written on the bottom.

Here is the initial version of the script that solves task 2:

A screenshot of a 6-line code. Line 1 reads E T 2 dot m. The square button on the top right pane is annotated.

A quick glance at this code shows that it is correctly typed and ready to execute. That can be verified with the green box on the right side of the editor’s window. Even with the execution of the script, no error will show up in the Command window. However, checking the obtained results of g shows that many anticipated data points are missing in the results. The error is on line 3. The semicolon is typed in instead of the colon operator to create an array of t. This is an implicit error or bug in the code that cannot be detected by the M-file editor. Here is the corrected code:

A screenshot of a 6-line code. Line 1 reads E T 2 dot m. Line 2 reads task 2 dot compute the values of g.

Here is the initial version of the answer script for task 3:

A screenshot of a 5-line code with an error message that says parse error at right parenthesis. The error symbols on the right are highlighted.

In this script, the editor detects two errors and one warning sign on line 5. The script contents can be executed up to line 5, and the following error message is displayed in the Command window:

Error: File: ET3.m Line: 5 Column: 7 Invalid expression. When calling a function or indexing a variable, use parentheses. Otherwise, check for mismatched delimiters.

Actually, there was one error: a misplaced semicolon instead of a comma within the plot() command on line 5: plot( t; f, 'b-'). There are two common functionalities of the semicolon for MATLAB, one of which is the termination of display results in the Command window and the end of row elements of an array. Therefore, in this example, the semicolon inside plot() is misplaced. Here is the corrected script:

A screenshot of a command window titled E T 3 dot m. Line 2 reads task 3 dot compute the value of f of t. The window has a 5-line command written in it.

Here is the initial solution script of task 4:

A screenshot of a command window for computation. It has an error message that says all matrix rows must be the same length. The two error symbols on the right margin are annotated.

It automatically detected an error (the mistyped semicolon instead of a comma) as an element separator of the array. With this error, the script cannot be executed.

Here is the corrected version of the script:

A screenshot of a command window for computation. The values are assigned for the variables on top and a 6-line command is written on the bottom.

Here is the script of task 5. It calls the scripts in tasks 1 to 4.

A screenshot of a 22-line code. The square box on the top right corner and the command on line 22 are highlighted.

The script editor does not show any problems or issues. However, when it is executed, the following error message pops up in the Command window:

Error using run (line 87) RUN cannot execute the file 'ET2.mlx'. RUN requires a valid MATLAB script Error in ET5 (line 11) run('ET2.mlx');

This error message indicates that there is a problem recognizing the file. That means the file name ET2.mlx is not the correct file name (the file extension is wrong); it has to be ET2.m instead.

Here is the corrected script of task 5:

A screenshot of a 22-line code titled E T 5 dot m. Line 2 reads task 5 dot execute all M forward slash M L X files.

By executing the last file, ET5.m, all other four scripts are also called and executed consecutively. Here are the computed outcomes from all scripts in the Command window:

Enter the value of a  =  2  Enter the value of b  =  3   Name             Size             Bytes  Class     Attributes   A1            1800x1              14400  double   Btab2          255x2               5162  table   Ccell3           1x2               1840  cell   Dstruct4         1x1              24800  struct   F              1x360               2880  double   H              1x360               2880  double   S              1x360               2880  double   T              501x5              20040  double   a                1x1                  8  double   alpha            1x360             2880  double   b                1x1                  8  double   beta             1x360             2880  double   delta            1x5                 40  double   f                1x101              808  double   g                1x255             2040  double   omegaN           1x1                  8  double   s                1x501             4008  double   t                1x101              808  double

Also, there is a plot figure (not shown here) from task 3 (ET3.m).

Note that there are many other common errors made while writing scripts that will be highlighted throughout the book. Moreover, there are a few common mistakes made while creating the function files that will be highlighted in the section dedicated to the function files.

Via these simple examples, you have seen how scripts, such as M-files and MLX-files, and the tools of M and MLX (Live) editors can be employed while writing scripts to detect common errors automatically. There are some other errors that are not detected by the M/MLX editors automatically that can be found only after executing the scripts. These include various operations (arithmetic, matrix, and array) that are performed with mismatched sizes of variables or improperly spelled MATLAB commands.

Note

Finding and fixing the errors you make while writing code is a good exercise for learning how to write great programs.

Cell Mode

In the M/MLX editors, the cell mode option is a handy tool to write well-structured code/scripts. Working in cell mode is simple and can be accomplished by typing %% and leaving one cursor space. This creates a new cell by default. Writing long scripts separated in cells for every separate operation helps you execute your code cell by cell and detect where the bugs/flaws are. It also helps you visually separate the code into distinct blocks that can be highlighted one at a time. This helps with the readability of the code while editing it. Let’s consider the following example.

The equation for an ellipse centered at the origin of the Cartesian coordinates (x, y) is \( \frac{x^2}{a^2}+\frac{y^2}{b^2}=1\ (A), \)where a and b are constants that determine the shape of the ellipse. The variables x, y are defined by \( x(u)=\frac{a\left(1-{u}^2\right)}{u^2+1},y(u)=\frac{2 bu}{u^2+1}, \)and \( u= tg\left(\frac{t}{2}\right) \) where 0 ≤ t ≤ 2π.

  1. 1)

    Compute the ellipse given in equation in (A) for a = 1.5, b=3.5 and plot it.

  2. 2)

    Plot and display the points of intersection of the two ellipses described by \( {x}^2+\frac{y^2}{4}=1 \) and \( \frac{x^2}{25}+{y}^2=1 \).

  3. 3)

    Compute three ellipses defined in (A) as a three-column array for these cases: a = [1, 2, 3], b=[3.5, 1, 2].

Here is the solution script of this exercise created in three cell modes representing answers for each subsection of the exercise. Each cell contains an answer script for each part of the given exercise. Cell 1 (part 1), composed of lines 2–9, computes the ellipse in (A) with respect to the values of a and b. Cell 2 (part 2), composed of lines 10–27, computes two ellipses and plots their values and, subsequently, displays intersecting points of the two ellipses. Cell 3 (part 3) computes three ellipses with respect to the values of a and b and plots the computed ellipses.

A screenshot of a 40-line code. Line 1 reads cell mode-based code writing. The command is divided into 3 parts, and part 3 is highlighted.

After writing the code in cell mode, you can execute each cell separately by using the Ctrl+Enter keys on the keyboard when the cursor is within the cell that is meant to be executed or using the and and tools of the M-file editor. Note that an alternative way of executing the selected part of a code is to hit the F9 key on the keyboard. The advantages of using cell mode is that you can execute and test each cell separately. If there are any errors, you can fix them without any interference with other cells. You can save considerable time and effort when you debug and correct long scripts.

Note

When you are writing long, extended scripts and debugging them, it is more efficient to use cell mode.

As noted, the M/MLX-file editors have many useful tools. For instance, they automatically detect common typographical errors. They detect and warn a user about the following:

  • Mistyped MATLAB built-in function/command names

  • Unclosed mathematical expressions with brackets, namely, (), {}, []

  • Misused/improperly used or missed mathematical operators, namely, +-*/\, ..., ( ), {}, []

  • Invalid syntaxes

  • Unused variable names

  • Suppress display of (lengthy) outputs

  • Which entries are numeric data, which entries are characters or text messages, and which entries are comments

  • Warning messages that let you know how to improve computation efficiency of a script

In addition, the M/MLX-file editors have the following tools:

  • Debugging modes, such as set/clear breakpoints, set/modify conditional breakpoints, enable/disable breakpoints, stop if errors/warnings

  • Working in a cell mode

  • Text editing options under text

  • Report writing by save and publish options

Debugging Mode

The dbstop function temporarily halts the execution of a script and provides the user with an opportunity to examine the local workspace. While debugging a script, you can set the breakpoints at specific lines in the Editor window by clicking that line in the left gutter. There are more than a dozen forms of dbstop function uses, as shown here:

    (1)  dbstop in FILE at LINENO     (2)  dbstop in FILE at LINENO@     (3)  dbstop in FILE at LINENO@N     (4)  dbstop in FILE at SUBFUN     (5)  dbstop in FILE     (6)  dbstop in FILE at LINENO if EXPRESSION     (7)  dbstop in FILE at LINENO@ if EXPRESSION     (8)  dbstop in FILE at LINENO@N if EXPRESSION     (9)  dbstop in FILE at SUBFUN if EXPRESSION     (10) dbstop in FILE if EXPRESSION     (11) dbstop if error     (12) dbstop if caught error     (13) dbstop if warning     (14) dbstop if naninf  or  dbstop if infnan     (15) dbstop if error IDENTIFIER     (16) dbstop if caught error IDENTIFIER     (17) dbstop if warning IDENTIFIER

The name FILE is the file name in which you want to perform the debugging operations. It has to be specified as a character vector of the string scalar. FILE can also include a full or partial path to the file directory. LINENO is a line number within FILE (the script in which the debugging operation is being performed), and N is an integer specifying the Nth anonymous function on the line. SUBFUN is the name of a subfunction within FILE. EXPRESSION is an executable conditional expression, specified as a character vector or string scalar. IDENTIFIER is a MATLAB message identifier (see the help for ERROR for a description of message identifiers). The AT and IN keywords are optional.

M-Lint Code Check

The command mlin() is used to check MATLAB code files for possible problems. When you run an M-Lint code check from the M-file Editor window, by choosing Tools ➤ M-Lint ➤ Show M-Lint Report, it will prompt you with a full report (on your M-file) of warning messages. For instance, it will check which variable is unused, which variable’s size changes on every loop iteration, what the opportunities are for improvement, which one of the employed built-in functions of MATLAB is deprecated, and so forth. The general command syntax of mlint() is as follows: >>mlint('filename'). Starting from MATLAB 2019a, mlint() is not recommended, and the checkcode() command is recommended instead.

Let’s consider the following example to demonstrate how to use the M-Lint code check tool:

Given {2x1 − 3x2 + x3 = 5 4x1 + 2x2 − 2x3 = 3 6x1 + 3x2 + 2x3 = 11, write the code to solve the given system of linear equations, and import the computed solutions along with the given data into an external Microsoft Excel file.

Here is the solution script:

A screenshot of a 7-line code. The command in line 7, xlswrite, is highlighted. The right margin has 3 error symbols.

The code (Code_Check.m) contains two warnings automatically detected by the M-file editor. They are related to the inv() and xlswrite() functions.

When you call this created code (Code_Check.m) using mlint() and checkcode(), you will get the following analysis report:

>> mlint('Code_Check.m') L 6 (C 5-7): INV(A)*b can be slower and less accurate than A\b. Consider using A\b for INV(A)*b or b/A for b*INV(A). L 7 (C 1-8): 'xlswrite' is not recommended. With appropriate code changes, use 'writematrix' or 'writecell' instead. >> checkcode('Code_Check.m') L 6 (C 5-7): INV(A)*b can be slower and less accurate than A\b. Consider using A\b for INV(A)*b or b/A for b*INV(A). L 7 (C 1-8): 'xlswrite' is not recommended. With appropriate code changes, use 'writematrix' or 'writecell' instead.

The analysis report also has recommendations. If you follow the recommendations and make the respective changes in the code (Code_Check.m), it looks like this:

A screenshot of a 7-line code. The command on line 7, writecell, is highlighted. A checkmark symbol is on the top right.

Now, the M-file editor shows no more warnings. Let’s run code checking again with the updated code (Code_Check.m).

>> mlint('Code_Check.m') >> checkcode('Code_Check.m')

The code checking produces no recommendations, which means the updated code is perfected.

Code Profiling

Code profiling measures where a program spends time and where the problems/errors are. By identifying the performance of your program, you can improve it. Code profiling can be started from the M-file Editor window by clicking the icon. The Code Profiling (Profiler) window pops up. The profile report contains the whole benchmarking report of your script (M-file) including extensive information on each command and operation, including how much the CPU spends obtaining the results. By studying a profile report of your script, you can learn how to improve simulation time efficiency. The profile mode is off by default and can be also switched on by using the >> profile on command. The profile summary report of any M-file or Simulink model can be generated and viewed with general syntaxes, for example:

Here’s another example:

>> profile on; Test; profile viewer

Here’s an example for Simulink models:

>> profile on; sim('My_Model'); profile viewer

Note

You can insert any M-file or MLX-file name (e.g., My_function.m, My_Code.mlx) or function file name (e.g., My_function.m) or Simulink model name (e.g., My_Model.mdl, Model_Sim.slx) between the two commands profile on; and profile viewer. Here’s an example: >> profile on; My_Code; profile viewer.

After running the code (Test.m), the comprehensive profile report of the code (Test.m) will pop up, as shown in Figure 2-2.

Figure 2-2
A screenshot of a window of profiler. The pane titled profile summary has a table for the function name, calls, total and self-time, and total time plot.

Profiler view results

The total processing time is 0.015 seconds. From the report, you can see for each function that the evaluation function took a significant amount of processing time. You can also view how much processing time is spent in each subfunction by clicking the function name in the profile report.

Dependency Report

The dependency report is used to identify all functions, scripts, and external programs (applications) that are called/used within our program. This report finds information about dependent files and tools of the current file that we have employed within our script built-in functions from MATLAB toolboxes and other M-files and function files from our current folder. This will be helpful before sharing our work with other users who may not have all the M-files, function files, and toolboxes that we have in our computer. The dependency report shows dependencies among MATLAB files in a directory and can be called with the following steps:

  1. 1.

    Select Desktop ➤ Current Directory and navigate to the directory containing MATLAB files for which we want to see the dependency report.

  2. 2.

    Click the Current Folder tab, and from the right-mouse button options, select Reports, and then select Dependency Report.

  3. 3.

    The dependency report of all MATLAB files will be shown automatically.

P-Codes

In MATLAB and Simulink, except for M-files (function files), with a file extension of *.m, *.mlx, *.mat, *.mdl, and *.slx files, there is also another important file type that is called P-code with a file extension of *.p that is very handy and recommended to create in some specific instances. The main reasons for creating a P-code file from an M-file are to prevent valuable files from being edited, to keep them secure, and to speed up the simulation time of scripts.

Specifically, here are some good reasons to create P-code:

  • To speed up the process of simulation in the MATLAB platform.

  • To keep valuable M-files secure to a certain extent; however, P-code should not be considered as a substitute for secure encryption.

  • P-code/files provide a simple means of hiding proprietary algorithms.

  • When you call an M-file function, MATLAB parses the M-code and stores the instructions as P-code in cache memory. P-code remains in memory until it is cleared using the clear command or until MATLAB quits.

  • P-code is platform-independent pseudocode for a virtual MATLAB machine.

  • Since P-files are in a binary format, their source code is hidden.

Here is how to create P-code:

  • To create P-code from a given M-file residing in the current folder, e.g., My_fileM.m, type the following in the Command window:

    >> pcode My_fileM.m

    After running the previously shown command, a P-code of the M-file My_fileM.m will be created under the same file name but with the extension of *.p instead of *.m.

  • To execute the created P-code called My_fileM.p, type in the Command window:

    >> My_fileM.p

  • Or type in the Command window:

    >> run My_fileM

This executes the created P-code even if we have in our current directory our primary M-file called My_fileM.m.

Some Remarks on Scripts/M/MLX-Files

Note the followings:

  • In general, any MATLAB commands can be executed from scripts or from the Command window. Which method is best depends on what tasks/computations or evaluations need to be performed. If there are simple computations composed in a one-step process and no repetitions are required, then there is no need to create M/MLX-files or scripts. On the other hand, when large computations with different operations including loop iterations and conditional statements are required, then writing M/MLX-files is the best option.

  • The error and warning messages will not only help you locate errors in your scripts or models but also provide some hints on what the causes of errors are and how to eliminate them. In fact, warning messages will help you make your programs more robust and also inform a user about the ignored data in computed/plotted outputs.

  • To write scripts and M-files, the M/MLX-file editors must be employed since they include a number of helpful tools. For instance, they automatically detect unused variables, the display of data sets, and the unclosed loops. They also enable you to work in cell and debug modes and help you detect errors and warnings about costly computations within loops, suggest memory allocation options, and do much more.

Display and Print Operators: display, sprintf, and fprintf

There are several commands and operators (built-in functions) to display computation results in the Command window or export them into external files compatible with MATLAB. They are disp(), display(), sprint(), and fprintf(). Out of these commands, disp() and display() are straightforward ways to display any comments, strings, or numerical values in the Command window without any additional formatting tools or characters. They are not robust enough to display any comments/strings and numerical values in various formats. They cannot write data into external files. On the other hand, sprint() and fprintf() can substitute all functions of disp() and display(). They can be used to print various data types in the Command window by using formatting operators and characters. Moreover, they can print textual and numerical data into external files. Let’s look at several examples to demonstrate how to employ these display and print commands.

Example 1

Given \( f(t)=\mathit{\sin}(t),t=\left[0,\frac{\pi }{4},\frac{\pi }{2},\frac{3\pi }{4},\pi \right] \). Displaying computation results of the function f (t) and its argument t with short explanatory comments in the Command window is straightforward with disp() and display().

t=[0, pi/4, pi/2, 3*pi/4, pi]; disp(['Sine @', num2str(t(1)),' is equal to: ', num2str(sin(t(1))) ]) disp(['Sine @', num2str(t(2)),' is equal to: ', num2str(sin(t(2))) ]) disp(['Sine @', num2str(t(3)),' is equal to: ', num2str(sin(t(3))) ]) disp(['Sine @', num2str(t(4)),' is equal to: ', num2str(sin(t(4))) ]) disp(['Sine @', num2str(t(5)),' is equal to: ', num2str(sin(t(5))) ])

These commands display the following in the Command window:

Sine @ 0 is equal to: 0 Sine @ 0.7854 is equal to: 0.70711 Sine @ 1.5708 is equal to: 1 Sine @ 2.3562 is equal to: 0.70711 Sine @ 3.1416 is equal to: 1.2246e-016

The displayed results are all correct and readable, but the demonstrated procedure is tedious. Note that there is a difference in the output from disp() and display(). The command disp() displays output without a variable name. By contrast, display() displays the variable name and its value like a simple calculation ending without a semicolon. Here’s an example:

>> D1=sind(90); >> display(D1) D1 =      1 >> disp(D1)      1 >> D1 D1 =      1 >> D1=sind(90) D1 =      1

Example 2

The command clock is a built-in command to show the current year/date/time according to a user’s computer clock in a row matrix format. Let’s display the current time in a more explicit way with some explanations. How do you do it with the disp() and display() commands?

>> format short G >> TT=clock TT =   Columns 1 through 5          2022           8            9            4            5   Column 6        37.261 >> display('This year is: '); disp(TT(1)) This year is:         2022 >> display('This month is: '); disp(TT(2)); This month is:     8 >> display('Day of this month: '); disp(TT(3)); Day of this month:      9 >> disp('Current time is '); display(['hour: ', num2str(TT(4))]); display(['minutes: ', num2str(TT(5))]) Current time is hour: 4 minutes: 5

The output is legible and explicit, but the commands are too long and inefficient from a programming point of view.

fprintf( )

For the previous two examples, the fprintf() command can be employed much more simply. The general syntax of this command is as follows:

fprintf(format, A, ...)

For example 1, to display the sine function values, fprintf() gives a much simpler solution, as shown here:

fprintf('Sine @ %1.5f is equal to: %2.5f\n', t, sin(t));

Here are the output results from the command fprintf():

Sine @ 0.00000 is equal to: 0.78540 Sine @ 1.57080 is equal to: 2.35619 Sine @ 3.14159 is equal to: 0.00000 Sine @ 0.70711 is equal to: 1.00000 Sine @ 0.70711 is equal to: 0.00000

The formatting specifiers, namely, %1.5f, %2.5f, and \n, used in this example define the field width and precision with the floating-point number format (%1.5f, %2.5f) and new line (\n). More details of formatting specifiers are given later in this section.

This is a much simpler and effortless method; it contains only one line of code.

For example 2, to display the time and date, fprintf() can be employed again as follows:

>> TT=clock; fprintf('Year:%g; Month: %g; Day: %g; Hour: %g; Min passed: %g\n',TT(1), TT(2), TT(3), TT(4), TT(5)) Year: 2022; Month: 8; Day: 13; Hour: 9; Min passed: 28

For such cases, sprintf() could be also an option. The general syntax of the command sprintf() is as follows:

str = sprintf(format, A, ...) [str, errmsg] = sprintf(format, A, ...)

Note that to display outputs (str string messages) from sprintf(), you need to use either the disp() or display() command again. So, sprintf() is less flexible than fprintf(). Note that sprintf() always returns a string. To demonstrate how to employ sprintf() more explicitly and improve the script created to solve a quadratic equation, let’s use the sprintf() command to display the computation results in the Command window with some additional information. Let’s compute the roots of a quadratic equation and display some information in the Command window. Here is the solution script (QuadEq1.m):

% QuadEq1.m % Solve quadratic equations based on coefficients of: a, b, & c disp('Solve: ax^2+bx+c=0') a=input('Enter value of a: '); b=input('Enter value of b: '); c=input('Enter value of c: '); D=b^2-4*a*c; [S, Errm]=sprintf('Discriminant of the equation is: %g', D); disp(S) % Roots x1=(-b+sqrt(D))/(2*a); x2=(-b-sqrt(D))/(2*a); % Display roots in the Command window [xr1, Errm1]=sprintf('Root1 of the equation is x1= %g', x1); disp(xr1); display(x1) [xr2, Errm2]=sprintf('Root2 of the equation is x2= %g', x2); disp(xr2); display(x2)

Let’s test the created M-file (QuadEq1.m) by executing it and providing the following entries (a=11, b=11, c=13) in the Command window:

Solve: ax^2+bx+c=0 Enter value of a: 11 Enter value of b: 12 Enter value of c: 13 Discriminant of the equation is: -428 Root1 of the equation is x1= -0.545455 x1 =   -0.5455 + 0.9404i Root2 of the equation is x2= -0.545455 x2 =   -0.5455 - 0.9404i

Note that within sprintf() the numerical data is defined by the % sign followed by a formatting sign/letter g that is called a conversion specifier. Here is a command syntax of declaring data formats with sprint() and fprintf():

[S, Errm]=sprintf('Discriminant of the equation is: %g', D);

Conversion specifications begin with the % character and contain these optional and required elements:

  • Flags (optional)

  • Width and precision fields (optional)

  • A subtype specifier (optional)

  • Conversion character (required)

These elements are used in the following order:

An illustration of conversion specification depicts, percentage space plus space 12.13d, and has the following elements, conversion character, precision, flags, and field width.

Flags are to control the alignment of the output, for instance, the - sign for the left justification of the output, the + sign for the right justification of the output, the space character for space before the value, and 0 to put a zero before the output. The field width is defined with a non-negative integer that specifies the number of digits or characters in the output, and the number (in precision) specifies the number of digits after the decimal point of the output; for example, %12.0 produces no decimal digits after the decimal digit number, and %12.13 produces 13 decimal digits after a decimal sign. Table 2-1 lists conversion characters, and Table 2-2 lists escape characters to specify nonprinting characters.Footnote 1

Table 2-1 Conversion Characters
Table 2-2 Characters for Escape Formatting

One of the most used escape formatting commands (Table 2-2) is \n. This is the escape character used to write the following data in a new line. Note that in the previous examples (examples 1 and 2), we have used \n within the fprintf() command.

Let’s consider the previously discussed quadratic equation example to display and write its real and complex roots. Note that this exercise will demonstrate how to employ sprintf() and fprintf().

There are several ways to display complex numbers (e.g., complex roots of the quadratic equation) in the form of R + I ∗ i explicitly with additional comments and then write/export them into an external file. They are to employ numerical conversions along with comments and to employ the string conversion character s.

Let’s start with the first way, which requires adding several formatting items from Tables 2-1 and 2-2 to display complex numbers correctly. Now the existing M-file (QuadEq1.m) will be updated with the following by employing a conversion function num2str() to obtain the complex roots converted into strings. Now there is no need to separate out real and imaginary components of the complex roots of the equation.

 [xr1, Errm1]=sprintf('Root1 of the equation is x1= %10s', num2str(x1)); disp(xr1); display(x1) [xr2, Errm2]=sprintf('Root2 of the equation is x2= %10s', num2str(x2)); disp(xr2); display(x2) % Or an alternative way: disp(sprintf('Root2 of the equation is x1= %10s', num2str(x1))) disp(sprintf('Root2 of the equation is x2= %10s', num2str(x2)))

After executing the updated script (QuadEq1.m), three input prompts to enter values for a, b, and c in a consecutive order are displayed; and after entering the following entries (a=11, b=12, c=13), the following display results of the given equation’s complex roots are obtained:

Solve: ax^2+bx+c=0 Enter value of a: 11 Enter value of b: 12 Enter value of c: 13 Discriminant of the equation is: -428 Root1 of the equation is x1= -0.54545+0.94037i x1 =      -0.54545 +    0.94037i Root2 of the equation is x2= -0.54545-0.94037i x2 =      -0.54545 -    0.94037i

Note that in this script fprintf() can be used instead of sprintf() in a similar manner that would make the code simpler. Thus, let’s employ fprintf() to display the complex roots of the quadratic equation and write the computation results of the quadratic equation into an external file.

A general syntax for writing data into an external file with fprintf() is as follows:

FileID=fopen('filename.extension', 'permission') fprintf(FileID, 'format', data); ... fclose(FileID)

Note that permission can be w for writing, r for reading, r+ for reading and writing, and a for appending permissions. MATLAB supports a few common data file types, such as *.txt, *.dat, *.xls, *.csv, *.jpeg, etc. Via format, a type of data is defined, and format in fprintf() is defined like in sprint(). Using the general syntax of writing/exporting data (existing data is discriminant and roots of the quadratic equation are saved in the workspace) into an external file, the following short script (DataWrite.m) writes the computed data (saved data in the workspace) into a file called DataWrite.txt:

% DataWrite.m - Write computed data into an external file fid1=fopen('Results_QE.txt', 'w'); fprintf(fid1,'Discriminant of the equation is: %g\n', D) fprintf(fid1,'Root1 of the equation is x1= %10s\n', num2str(x1)) fprintf(fid1,'Root2 of the equation is x2= %10s\n', num2str(x2)) fclose(fid1); open('Results_QE.txt')

Note that this script first creates a new external file called Results_QE.txt with the permission to write in it. This external file (Results_QE.txt) has a file ID called fid1 (note that a file ID can be named freely) through which it can be called up to write in it assigned data, D, and the roots x1 and x2. Within the fprintf() command, the \n escape character is used to write the following data in a new line. Finally, the data-writing procedure ends with a file close command: fclose(fid1). This is a standard procedure of exporting data of any size and of any format into an external file. This procedure of data export is covered more extensively via different examples in other chapters of the book. After executing the previously shown script, the following *.txt file content is displayed in the M-file Editor window:

Discriminant of the equation is: -428 Root1 of the equation is x1= -0.54545+0.94037i Root2 of the equation is x2= -0.54545-0.94037i

There are many different format tools for data display and writing to external files that all can be employed more freely with respect to the given tasks. The demonstrated script can be improved further with data entries and by displaying/writing the calculated data. These will be discussed further with control statements in the following section.

Control Statements: [if, else, elseif, end], [switch, case, end]

The control statements [if ... elseif... else ... end] are also called conditional statements or Boolean operators and are employed to select logically which block of the code is to be executed while running the whole script according to the given input entries or computed results or defined outputs of the script. They are one of the few most crucial programming operators in all programming languages. These operators are employed in building and branching structures of programs (or codes). The general structure of these control statements follows:

if <logical statement A is true>            DO X Operations elseif <logical statement B is true>            DO Y operations ... else           DO W operations end

This indicates that if logical statement A is true, then X operations will be executed. If logical statement B is true, Y operations will be executed. If none of the previous logical statements is true, W operations will be executed.

Note that if there is only one logical statement, then elseif is not needed, and else is used directly instead of elseif.

Conditional operations can be expressed in two different ways: either on operational forms or on M/MLX-file forms. The conditional and logic statements given in Table 2-3 are applicable to all logical operations and conditional statements used in M/MLX-files/scripts.

Table 2-3 Control Logical Operators and Their Descriptions

Note

The operations < versus lt(), > versus gt(), <= versus le(), >= versus ne(), ~= versus ne(), == versus eq(), & versus and(), | versus or() can be used interchangeably and lead to no difference in code performance.

In various examples, we employ these operators and their syntaxes interchangeably. Let’s consider several examples to demonstrate how to employ the control statements given in Table 2-3.

Example 1

The command clock displays the current year/date/time of a user computer in a row matrix form. Let’s display the data in a readable format with some additional textual information. Here is a possible solution script (TimeDisp.m) of the given problem with the clock command:

% TimeDisp.m  Time Display display(clock); NOW=fix(clock);% Round to nearest integers fprintf('This year is: %g \n', NOW(1)); if NOW(2)==1     display(['Date is January ' num2str(NOW(2))]); elseif NOW(2)==2     display(['Date is February ' num2str(NOW(2))]); elseif NOW(2)==3     display(['Date is March ' num2str(NOW(2))]); elseif NOW(2)==4     display(['Date is April ' num2str(NOW(2))]); elseif NOW(2)==5     display(['Date is May ' num2str(NOW(2))]); elseif eq(NOW(2),6)     display(['Date is June ' num2str(NOW(2))]); elseif eq(NOW(2),7)            % No difference between eq() and ==     display(['Date is July ' num2str(NOW(2))]); elseif eq(NOW(2),8)     display(['Date is August ' num2str(NOW(2))]); elseif eq(NOW(2),9)     display(['Date is September ' num2str(NOW(2))]); elseif eq(NOW(2),10)     display(['Date is October ' num2str(NOW(2))]); elseif eq(NOW(2),11)     display(['Date is November ' num2str(NOW(2))]); else     display(['Date is December ' num2str(NOW(2))]); end if NOW(4)>=12 fprintf('Current time:  %g PM - %g min - %g sec\n', ...         NOW(4), NOW(5), NOW(6)) else fprintf('Current time:  %g AM - %g min - %g sec\n', ...         NOW(4), NOW(5), NOW(6)) end

By running the script, the following outputs are displayed in the Command window:

ans =   Columns 1 through 5          2018           11            1            4           51   Column 6        34.932 This year is: 2018 Date is November 1 Current time:  4 AM - 51 min - 34 sec

Let’s consider the previous example with a quadratic equation and correct the display of computed roots with disp, sprintf, fprintf, if, elseif, and else to demonstrate how to employ these programming operators.

Example 2

Here is one of the possible solution scripts (Quad_Eq2.m) of computing roots and displaying the roots of quadratic equations with additional comments:

% Quad_Eq2.m % Solve quadratic equations based on coefficients of: a, b, & c a=input('Enter value of a: '); b=input('Enter value of b: '); c=input('Enter value of c: '); fprintf('Solve: (%3g)x^2+(%3g)x+(%3g)=0\n', a,b,c) D=b^2-4*a*c; % Roots x1=(-b+sqrt(D))/(2*a); x2=(-b-sqrt(D))/(2*a); if lt(D,0) disp('This equation does not have real value roots!'); Dm=sprintf('Because discriminant is negative. D = %g', D); disp(Dm) fid1=fopen('Results_QE.txt', 'w'); fprintf(fid1, 'This equation does not have real value \n'); fprintf(fid1, 'roots!\n'); fprintf(fid1,'Because discriminant is negative. D = %g\n', D); fprintf(fid1,'Complex Root1: x1= %10s\n', num2str(x1)); fprintf(fid1,'Complex Root2; x2= %10s\n', num2str(x2)); fclose(fid1); open('Results_QE.txt'); elseif eq(D,0) disp('This equation has one unique root! '); disp('Because discriminant is zero: D = 0 '); fid1=fopen('Results_QE.txt', 'w'); fprintf('This equation has one unique root! \n'); fprintf(fid1,'Because discriminant is zero: D = 0 \n'); fprintf(fid1,'Unique Root: x = %g \n', x1); fclose(fid1); open('Results_QE.txt'); else     disp('This equation has two roots! ');     Dm =sprintf('Because discriminant is: D = %g ', D); disp(Dm);     fid1=fopen('Results_QE.txt', 'w');     fprintf(fid1,'This equation has two roots \n');     fprintf(fid1,'Because discriminant is: D = %g \n', D);     fprintf(fid1,'Real Root1 is: x1= %g \n', x1);     fprintf(fid1,'Real Root2 is: x2= %g \n', x2);     fclose(fid1); open('Results_QE.txt'); end

In this script, a few sets and combinations of [if, elseif, else, end] conditional statements are employed that provide nice outputs. Also, verbal versions of gt, lt, and eq of the ≤, ≥ , < , > , = logical operators are employed. Yet, the robustness of the script is still insufficient. For instance, the user may enter wrong entries by typing the value of c for b or a, or vice versa, or skip entering any of the coefficients. As a result, the previous script produces the wrong output. To attain the full robustness of the script for different case scenarios and user entries including mistakes while entering input values, a loop control statement with [while ... end] will be employed. We discuss it in the following section.

Example 3

This example warns drivers about their driving speed based on where they are driving (school zone, residential/business district, unpaved town road, two and multilane highways, interstate highways). The speed limits in North Dakota are used in this example.

% Drive_Safe.m gives a warning sign what is the speed limit and % how to behave in specific roads, highways, expressways, etc. % E.g. CS is the only input variable % Speed Limit [1] School area: 20 [mph] % Speed Limit [2] Residential and business area: 25 [mph] % Speed Limit [3] Town gravel roads: 55 [mph] % Speed Limit [4] Two-lane highways: 65 [mph] % Speed Limit [5] Multi-lane highways: 70 [mph] % Speed Limit [6] Divided Interstate: 75 [mph] CS = input('Enter your car"s current speed in [mph]:    '); disp('Choose WHERE you are driving:  ') disp('[1] School area;  [2] Residential and Business Area; ') disp('[3] Town gravel roads; [4] Two-lane Highways; ') disp('[5] Multi-lane Highways; [6] Divided Interstate Roads; ') DZone = input('Enter your drive zone, e.g., 1, 2, 3, ... 6:  '); if isempty(DZone) || DZone >7 || DZone<0     warndlg('Not clear where you are driving!') elseif CS ==0     warndlg('Your car is not moving') elseif CS<0     warndlg('Your car is moving in a rear direction that is DANGEROUS! ') else     if DZone ==1 && CS > 0 && CS<10        fprintf('Your speed = %g [mph] is too slow \n ', CS)       fprintf('even if it is during the student arrival/departure time \n')        warndlg('Speed UP to make your car speed around 15 mph!')     elseif  DZone ==1 && CS > 10 && CS<20         fprintf('Your speed = %g [mph] is OK in a school area \n', CS)         fprintf('during the student arrival/departure time \n')         warndlg('Keep your car speed around 15...20 mph!')     elseif DZone ==1 && CS >20     fprintf('Your speed = %g [mph] is TOO fast for a school area \n', CS)     warndlg('DANGER! Slow DOWN up to 20 mph!')     elseif DZone ==2 && CS > 15 && CS <20 fprintf('Your speed = %g [mph] is too slow for a residential area!\n', CS) warndlg('Speed up! Speed limit for residential/business areas is 25 mph')     elseif DZone == 2 && CS > 20 && CS < 28     fprintf('Your speed = %g [mph] is adequate for a residential area!', CS)     warndlg(' Do not speed over 25 mph!')     elseif DZone == 2 && CS > 28     fprintf('Your speed = %g [mph] is higher for a residential area!\n', CS)     warndlg(' DANGER!  Slow DOWN and do not speed over 25 mph!')     elseif DZone == 3 && CS < 48  && CS > 25     fprintf('Your speed = %g [mph] is slower for gravel town roads!\n', CS)     warndlg(' Speed up to 55 mph!')     elseif DZone == 3 && CS > 48  && CS < 58 fprintf('Your speed = %g[mph] is within limits for gravel town roads!\n',CS)         warndlg(' Keep your speed around 55 mph!')     elseif DZone == 3 && CS > 58         fprintf('Your car speed = %g [mph] is beyond \n', CS)         fprintf('the limits for a gravel town roads! \n')         warndlg(' DANGER!  Slow DOWN up to 55 mph!')     elseif DZone == 4 && CS > 55  && CS < 60         fprintf('Your speed = %g [mph] is slower for two-lane HW!\n', CS)         warndlg(' Speed up to 65 mph!')     elseif DZone == 4 && CS > 60  && CS < 68 fprintf('Your speed = %g[mph] is within the limits for two-lane HW! \n', CS)         warndlg(' Keep your speed around 65 mph!')     elseif DZone == 4 && CS > 68         fprintf('Your speed = %g [mph] is beyond  \n', CS)         fprintf('the limits for two-lane HW! \n')         warndlg(' DANGER!  Slow DOWN up to 65 mph!')     elseif DZone == 5 && CS > 55  && CS <65         fprintf('Your speed = %g [mph] is slower than \n' , CS)         frpintf('the speed limits for multi-lane lane HW! \n')         warndlg(' Speed up to 70 mph!')     elseif DZone == 5 && CS > 65  && CS <75         fprintf('Your speed = %g [mph] is within \n', CS)         fprintf('the speed limits for multi-lane lane HW! \n')         warndlg(' Keep your speed around 70 mph!')     elseif DZone == 5 && CS > 75         fprintf('Your speed = %g [mph] is beyond \n', CS)         frintf('the speed limits for multi-lane lane HW! \n')         warndlg(' DANGER! Slow DOWN up to 70 mph!')     elseif DZone == 6 && CS > 60  && CS <70         fprintf('Your speed = %g [mph] is slower than \n', CS)         fprintf('the speed limits for Divided Interstate in ND! \n')         warndlg(' Speed up to 70 mph!')     elseif DZone == 6 && CS > 70  && CS <78         fprintf('Your speed = %g [mph] is within \n', CS)         fprintf('the speed limits for Divided Interstate in ND! \n')         warndlg(' Keep your speed around 75 mph!')     else         fprintf('Your speed = %g [mph] is beyond  \n', CS)         fprintf('the speed limits for Divided Interstate in ND! \n')         warndlg(' DANGER!  Slow DOWN up to 75 mph!')     end end

In this answer script to the given exercise, the conditional statements or Boolean operators [if ... elseif ... else ... end] are used twice. The first [if... elseif ...elseif... else ... ] identifies according to the user entries whether the user has specified or not where they are driving (DZone) and what their car speed (CS) is. The second [if... elseif ... ... else ... end] starts only if the first [if...elseif ...] conditions are met or, in other words, the user has entered their driving speed and driving zone.

If the user information is valid for the predefined six driving zones, then under [elseif CS ==0], it verifies the given car is moving. If it is moving, [elseif CS<0] indicates in which direction (backward for negative speed values). The last [else] evaluates the positive values of car speed.

Beyond this first [else], all positive values (forward movement of a car) and a second loop of [if ... elseif ... ... else ... end] are executed. They define the speeding level and provide respective warning signals to the driver with respect to where (zones and roads) they are driving and what their speed is.

Let’s test the script with different input speed values and the different driving zones.

Case 1

The given car is driving at 9 mph in a school zone.

Enter your car"s current speed in [mph]:    9 Choose WHERE you are driving: [1] School area;  [2] for Residential and Business Area; [3] Town gravel roads; [4] Two-lane Highways; [5] Multi-lane Highways; [6] Divided Interstate Roads; Enter your drive zone, e.g. 1, 2, 3, ... 6:  1 Your car speed = 9 [mph] is too slow  even if it is during the student arrival/departure time

In addition, the following warning dialog box is displayed:

A screenshot of a dialog box titled warning dialog. The warning in it reads speed up to make your car speed around 15 miles per hour exclamation mark with an O K button on the bottom.

Case 2

The given car is driving at 72 mph on a two-lane highway.

Enter your car"s current speed in [mph]:    72 Choose WHERE you are driving: [1] School area;  [2] for Residential and Business Area; [3] Town gravel roads; [4] Two-lane Highways; [5] Multi-lane Highways; [6] Divided Interstate Roads; Enter your drive zone, e.g., 1, 2, 3, ... 6:  4 Your car speed = 72 [mph] is beyond the limits for two-lane HW!

The following warning dialog box is displayed:

A screenshot of a dialog box titled warning dialog. The warning in it reads danger exclamation mark slow down up to 65 miles per hour exclamation mark with an O K button on the bottom.

Case 3

The given car is driving at 77 mph on a divided interstate highway.

Enter your car"s current speed in [mph]:    77 Choose WHERE you are driving: [1] School area;  [2] for Residential and Business Area; [3] Town gravel roads; [4] Two-lane Highways; [5] Multi-lane Highways; [6] Divided Interstate Roads; Enter your drive zone, e.g., 1, 2, 3, ... 6:  6 Your car speed = 77 [mph] is within the speed limits for Divided Interstate in ND!

The following warning dialog box is displayed:

A screenshot of a dialog box titled warning dialog. The warning in it reads, keep your speed around 75 miles per hour exclamation mark with an O K button on the bottom.

Another set of control statements is [switch, case, otherwise, end]. These statements have one big advantage over [if, else, elseif, end]: they can handle many cases and simplify the code. They have the following general syntax structure:

switch expression of scalar or string (variable)      case variable value1     A statements      case variable value2      B statement      case variable value3      C statement ...      otherwise      X, ... W statements end

Let’s look at a simple example to understand how the conditional statements [switch, case, otherwise, end] operate.

Example 4

Determine whether the user-entered integer from 1 to 50 is odd or even or a prime number. The following script (Num50Type.m) defines the type of any integer from 1 to 50:

% Num50Type.m - Defines entered integer type clear all; clearvars; clc N=input('Enter ANY integer up to 50:  '); if N<=50 fprintf('Your entry is: %d \n', N) switch N case mod(N,2)==0  fprintf('you have entered %g which is EVEN number \n', N) case {9,15,21,25,27,33,35,39,45,49} fprintf('You have entered %g which is ODD number but not prime\n', N) otherwise %N=[3,5,7,11,13,17,19,23,29,31,37,41,43,47]  fprintf('You have entered %g which is PRIME number \n ', N) end else disp('This code works with integers up to 50 to identify if they are even, odd or prime!') end

If you enter 23 as an input, you will get the following output in the Command window:

Enter ANY integer up to 50:  23 You have entered 23 which is PRIME number

This script correctly defines all entered numbers up to 50 (including 50); however, we may still improve its robustness by adding conditional statements and while loops to verify whether a user entry is correct and within the range of 1 to 50.

The robustness of the scripts with the control branching statements [if, elseif, else, end] can be improved by employing them within loop statements, namely, [while ... end] and [for ... end], which will be discussed via examples in the following section.

Loop Control Statements: while, for, continue, break, end

There are two types of loop control statements, namely, [while...end] and [for...end]. A first loop control statement is [while...end], and its general syntax is as follows:

while expression is NOT true perform A, B, C,..., W operations end

Unlike [if .. elseif ... else... end] statements, the [while...end] loop keeps executing the the following [A, B, C,..., W] operations until the expression behind the [while] operator becomes valid. Once the expression becomes true/valid, the execution process halts.

Example 1

To compute the sum of all odd numbers from 1 up to 100 using the [while ... end] loop control (Sum100.m), use this:

% Sum100.m sums of all odd numbers with while Sum=0; N=1; while ne(N, 100) if ne(mod(N,2),0) % Verifies all odd numbers are added.     Sum=Sum + N; else              % Verifies if the number is even, NO sum. end     N=N+1; end disp(['Sum of all odd numbers 1...100 is:  ', num2str(Sum)]);

This loop-based script (Sum100.m) will keep running until the iteration process reaches the end value of 100. The [if ... else ... end] conditional statements verify if the number is odd or even with the help of mod(). The iteration loop is used to compute the remainder of N/2. If the number is odd, the sum will take place; otherwise, it will be ignored.

Note

In many summation types of exercises that use [while ... end] and [for ... end] iteration loops, users have difficulty understanding the computation algorithm and writing the code to perform the summation process. The summation algorithm does not appear to be intuitive for many beginners in programming. Their difficulty comes from the fact that they overlook the necessity of assigning 0 to the sum variable in the initial step of the summation process. This means that adding any number to 0 gives the same number back. Subsequently, within a [for ... end] or [while ... end] loop, this summation variable will get a new value in each iteration. For example, this is what it looks like for the previous example:

Step 1. Sum(1) = 0;

Step 2. Sum(2) = Sum(1)+N(1) = 0+1=1; when N(1)= 1 and ne(mod(N(1),2), 0) is valid;

Step 3. Sum(3)=Sum(2)=1; when N(2)= N(1)+1=2 and because N(2)/2 = 1 and remaining “0” ← ne(mod(N,2), 0) is not valid.

Step 4. Sum(4)=Sum(3)+N(3)=1+3 =4; when N(3)=N(2)+1=2+1=3 and ne(mod(N(3),2), 0) is valid;

Step 5. Sum(5)=Sum(4)=4; when N(4)=N(3)+1=3+1=4; because N(4)/2 = 2 and remaining “0” ← ne(mod(N(4),2), 0) is not valid.

Step 6. Sum(6)= Sum(5)+N(5)=4+5=9; when N(5)=N(4)+1=4+1=5 and ne(mod(N(5),2), 0) is valid;

And so on. The iteration process continues until N equals 100.

The final output of the script in the Command window is as follows:

Sum of all odd numbers 1...100 is:  2500

Example 2

To better understand how to employ the control loop statement [while ... end], let’s look at the example of solving a quadratic equation: ax2 + bx + c = 0.

Let’s say the problem is that users can enter the values of a, b, c in the wrong order or mistype their values or enter wrong numbers.

To make a program more robust and resolve any wrong entries, the conditional operators [if ... elseif ... else ... end] are employed along with the [while ... end] loop iteration operators. The following is one of the possible solutions to the problem. The script (Quad_Eqn.m) is robust. It accepts different entries and computes all possible roots, real and complex, and then displays them correctly in the Command window. It resolves many possible wrong entries such as wrong values, wrong data sizes, or mixed-up values of a, b, c. Note that a first while loop statement in the script verifies the size of the entry row array containing the values of a, b, c, and a second one with the conditional operator [if ... else ... end] verifies the order correctness of the a, b, c entries.

% Quad_Eqn.m solves quadratic equations based on the user entries for: % a, b, c clearvars; clc SIZE_chk = 0; while SIZE_chk ~=1     disp('Solution of: ax^2+bx+c=0')     abc=input('Enter values as [a, b, c]:   ');     SIZE_abc=numel(abc);     if SIZE_abc ==3         SIZE_chk=1;         a=abc(1);         b=abc(2);         c=abc(3);         CorrectEntry=0;         while CorrectEntry~=1             if SIZE_abc == 3                 CorrectEntry=1; CorrectABC=0;                 % Check the order of a, b, c                 while CorrectABC~=1                     disp('Is this the equation you"d like to find roots?')                     disp('   ')                     Eqn=sprintf(' %g*x^2+(%g)*x + (%g)=0', a, b, c);                     disp('   ')                     disp(Eqn);             CorrectABC=input('If yes, enter 1, otherwise any integer!  ');                     disp('   ')                     if CorrectABC~=1                         abc=input('Enter values as [a, b, c]:   ');                         a=abc(1); b=abc(2); c=abc(3);                     end                 end                 D=b^2-4*a*c;                 % Roots                 x1=(-b+sqrt(D))/(2*a); x2=(-b-sqrt(D))/(2*a);                 if lt(D,0)                     disp('The equation has no real roots!');                     Dm=sprintf('Because discriminant <0. D = %g', D);                     disp(Dm)                     % Display the results                     fprintf(' %g*x^2+(%g)*x + (%g)=0\n', a, b, c);                     fprintf('It does not have real roots!\n');                     fprintf('Because its discriminant <0. D=%g\n',D); fprintf('Complex Roots are: x1=%10s; x2=%10s\n', num2str(x1),num2str(x2));                 elseif eq(D,0)                     disp('This equation has one unique root! ');                     disp('Because discriminant is zero. D=0 ');                     fprintf('%g*x^2+(%g)*x + (%g)=0\n', a, b, c);                     fprintf('It has a unique root! \n');                     fprintf('Because discriminant is "0". D=0 \n');                     fprintf('Unique Root: x = %g \n', x1);                 else                     disp('This equation has two real roots! ');      [Dm, Errm2]=sprintf('Because discriminant >0. D = %g ', D); disp(Dm);                     fprintf(' %g*x^2+(%g)*x + (%g)=0\n', a, b, c);                     fprintf('It has two real roots \n');                     fprintf('Because discriminant >0. D = %g\n', D);      fprintf('Roots of the equation are x1= %g; x2= %g \n', x1, x2);                 end             else                 CorrectEntry=0;                 disp(' a, b, c cannot have more than 1 element (value)');                 disp('Re-enter values of a, b, c');                 disp('    ')                 abc=input('Enter values as [a, b, c]:   ');                 a=abc(a); b=abc(2); c=abc(3);                 sa=numel(1); sb=numel(b); sc=numel(c);             end         end     else fprintf('Your entry is wrong \n') fprintf('Enter the correct entries for [a, b, c] as a row vector in [ ]: ')     end end

The created script is tested for robustness with intentionally wrong entries for a, b and c as stated in cases 1 and 2.

Solution of: ax^2+bx+c=0 Enter values as [a, b, c]:   [12 1 1 1 ] Your entry is wrong Enter the correct entries for [a, b, c] as a row vector in [ ]:  Solution of: ax^2+bx+c=0 Enter values as [a, b, c]:   [12 1 1 1 ] Your entry is wrong Enter the correct entries for [a, b, c] as a row vector in [ ]:  Solution of: ax^2+bx+c=0 Enter values as [a, b, c]:   [1 2 1 1 ] Your entry is wrong Enter the correct entries for [a, b, c] as a row vector in [ ]:  Solution of: ax^2+bx+c=0 Enter values as [a, b, c]:   [1 2 1  ] Is this the equation you"d like to find roots?  1*x^2+(2)*x + (1)=0 If yes, enter 1, otherwise any integer!  0 Enter values as [a, b, c]:   [1 1 2] Is this the equation you"d like to find roots?  1*x^2+(1)*x + (2)=0 If yes, enter 1, otherwise any integer!  1 The equation has no real roots! Because discriminant <0. D = -7  1*x^2+(1)*x + (2)=0 It does not have real roots! Because its discriminant <0. D=-7 Complex Roots are: x1=-0.5+1.3229i;   x2=-0.5-1.3229i

From the previous simple example, it is clear that the [while ... end] loop operations have more power than the [if ... elseif ... else ... end] operators to enhance the robustness of scripts.

A second loop control statement is [for ... end] that has the following general syntax:

for i=startloop:stepsize:endloop      Iteration 1      Iteration 2 ...      Iteration N end

The [for ... end] loop control statement works in the following fashion. It starts executing every statement of [1, 2, ..., N] starting from startloop for every step, with a step equal to stepsize until the loop iteration reaches the value of endloop, which corresponds to N number of iterations.

Note

If the step size is not specified when you’re assigning vector spaces or index ranges in [for ... end] loops, the default step size is 1.

Example 3

Compute the sum of all odd numbers within [1, 20] with the [for ... end] loop (Sum20odd.m).

% Sum20odd.m sums odd numbers within 0...20 with for loop clearvars; S=0; for N=1:20; if rem(N,2)==0 %Verifies if the number is even, then no sum.         S=S; else           %All odd numbers are added:         S=S+N; end end fprintf('Sum of all odd numbers 1 to %g is equal to %g \n', N, S)

The [if ... else ... end] conditional statements determine whether the number is odd. If the number is odd, it is added to the summation variable (S). Otherwise, nothing will be added to the summation variable (S). The algorithm behind this script is the same one in Example 1, and this short script is an alternative solution to Example 1. The only difference here is that the number of odd numbers is 20.

Two alternative, simpler solutions of this example using [for ... end] and [while ... end] are as follows:

% Sum20odd_alt.m sums odd numbers within 0...20 with [for ... end] loop clearvars; S=0; for N=1:2:20     S=S+N; end fprintf('Sum of all odd numbers 1 to 20 is equal to %g \n', S) % Sum of odd numbers within 0...20 with [while ... end] loop clearvars; S=0; jj=1; while le(jj,20)     S=S+jj; jj=jj+2; end fprintf('Sum of all odd numbers 1 to 20 is equal to %g \n', S)

The computation algorithm of this script [for ... end] is as follows:

  1. 1.

    S(1) = 0

  2. 2.

    S(2)=S(1)+N(1)=0+1=1 when N(1)=1

  3. 3.

    S(3)=S(2)+N(2)=1+3=4 when N(2)=3 because the step size is equal 2 (i.e., N(2)=N(1)+2=1+2=3)

  4. 4.

    S(4)=S(3)+N(3)=4+5=9 when N(3)=5 because ... N(3)=N(2)+2=3+2=5

  5. 5.

    And so on. The iteration loop runs until N = 20. In fact, in this case, N cannot be 20 because the step size is 2 and the maximum value of N will be 19.

Finally, the outputs of the scripts are identical:

Sum of all odd numbers 1 to 20 is equal to 100

As demonstrated, the [for ... end] loop can be easily substituted by the [while ... end] loop or vice versa; their efficiencies are similar. However, in some specific examples (e.g., Example 2), the robustness gained by using [while ... end] cannot be attained using [for ... end]. Theoretically, in some problems (e.g., Example 2), [while ... end] can be substituted by [for ... end] when the number of iterations is unknown.

Note

In many loop iteration-based computation problems, [for ... end] can be easily substituted by the [while ... end] loop and vice versa. Their computation efficiencies are similar. However, there are many specific cases, where [while ... end] operations are employed to attain the high robustness of the script, where [for ... end] cannot provide as much robustness and flexibility as [while ... end]. This is illustrated in Example 2.

It is recommended to use ii or jj for loop iterations for indices so as not to get confused with imaginary numbers, which use i and j as reserved in MATLAB by default. If these letters (i and j) are employed for indices, then sqrt(-1) can be used for imaginary numbers alternatively, or you can clear these variables from the workspace.

Example 4

Evaluate the square and cubic powers of even numbers (1 to 10) with the loop control statements for and end.

Here is one of the possible solution scripts (SqCube10.m) of the exercise. Note in this example startloop=2, stepsize=2, and endloop=10.

% SqCube10.m computes square and cube of 2...10 %%  [for  ... end] for k=2:2:10     Square = k^2;     Cube   = k^3;     fprintf('Square of %g is %g \n', k, Square);     fprintf('Cube of %g is %g \n'  , k, Cube); end %% Alternative way: [while ... end] jj =2; while le(jj, 10)      Square = jj^2;     Cube   = jj^3;     fprintf('Square of %g is %g \n', jj, Square);     fprintf('Cube of %g is %g \n'  , jj, Cube);     jj =jj+2; end

When the script is executed, the following will be displayed in the Command window:

Square of 2 is 4 Cube of 2 is 8 Square of 4 is 16 Cube of 4 is 64 Square of 6 is 36 Cube of 6 is 216 Square of 8 is 64 Cube of 8 is 512 Square of 10 is 100 Cube of 10 is 1000

Example 5

Evaluate the square and cubic powers of odd numbers (1 to N) with the loop control statements for and end.

Note that this exercise is similar to Example 4 with two major differences. It uses only odd numbers to compute squares and cubes and performs calculations until it reaches the user-defined N value.

Here is one of the possible solution scripts (SqCubeN.m) of the exercise. Note in this example startloop=1, stepsize=2, and endloop=N for the [for end] loop. For the [while end] loop, the starting value of the loop is 1 (jj = 1).

% SqCube_N.m computes square and cube of all odd numbers up to N %%  [for  ... end] N = input('Enter N =   '); for ii=1:2:N     Square = ii^2;     Cube   = ii^3;     fprintf('Square of %d is %d; Cube is %d \n', [ii, Square Cube]) end %% Alternative way: [while ... end] N = input('Enter N =   '); jj =1; while le(jj, N)     Square = jj^2;     Cube   = jj^3;     fprintf('Square of %d is %d; Cube is %d \n', [jj, Square Cube])     jj =jj+2; end

When you run the script and enter 13 for N, the following will be displayed in the Command window:

Enter N =   13 Square of 1 is 1; Cube is 1 Square of 3 is 9; Cube is 27 Square of 5 is 25; Cube is 125 Square of 7 is 49; Cube is 343 Square of 9 is 81; Cube is 729 Square of 11 is 121; Cube is 1331 Square of 13 is 169; Cube is 2197 Enter N =   13 Square of 1 is 1; Cube is 1 Square of 3 is 9; Cube is 27 Square of 5 is 25; Cube is 125 Square of 7 is 49; Cube is 343 Square of 9 is 81; Cube is 729 Square of 11 is 121; Cube is 1331 Square of 13 is 169; Cube is 2197

Example 6

Compute the series \( 1-\frac{1}{2}+\frac{1}{3}-\frac{1}{4}+\frac{1}{5}-\frac{1}{6}+\frac{1}{7}\dots \) by using [for ... end] and [while ... end].

Here are five possible solution scripts of the given exercise gathered within one script called SumSeries.m:

% SumSeries.m computes a sum of Series: %% Version A. [for ... end] clearvars sign=1; S=0; N=input('Enter number of series to compute:  '); for n=1:N     S=S+sign/n;     sign=-sign; end fprintf('Sum of %g series is equal to %2.5f \n', n, S) %% Version B. [for ... end] clearvars S N sign S=0; sign=1; N = input('Enter number of series to compute:  '); for k=1./(1:N)     S=S+sign*k;     sign=-sign; end fprintf('Sum of %g series is equal to %2.5f  \n', N, S) %% Version C. [for ... end] clearvars S N S=1; N = input('Enter number of series to compute:  '); for k=2:N     if eq(mod(k,2), 0)         S=S-1/k;     else         S=S+1/k;     end end fprintf('Sum of %g series is equal to %2.5f  \n', k, S) %% Version D. [while ... end] clearvars sign=1; S=0; N = input('Enter number of series to compute:  '); n = 1; while n<N+1     S=S+sign/n;     n=n+1;     sign=-sign; end fprintf('Sum of %g series is equal to %2.5f \n', n, S) %% Version E. [while ... end] clearvars S N S=0; N=input('Enter number if series to compute:  '); ii=1; while ii~=N+1 if mod(ii,2)==0         S=S-1/ii; else         S=S+1/ii; end     ii=ii+1; end fprintf('Sum of %g series is equal to %2.5f \n', ii, S)

All of these solution methods with [for ... end] and [while ... end] result in identical solutions. It must be noted that the MATLAB function mod(N, 2) defines whether the number is even or odd, which works in this script to separate the even and odd components of ii and k.

In all of the previous examples, the last final values from the iteration processes are saved. What about saving the values from all iteration steps?

%% Version A. [for ... end] clearvars sign=1; S=0; N=input('Enter number of series to compute:  '); for n=1:N     S=S+sign/n;     SS(n)=S;     sign=-sign;     fprintf('Sum of %g series is equal to %2.5f \n', n, SS(n)) end %% Version B. [for ... end] clearvars S N sign S=0; sign=1; ii=1; N = input('Enter number of series to compute:  '); for k=1./(1:N)     S=S+sign*k;     SS(ii)=S;     sign=-sign;     fprintf('Sum of %g series is equal to %2.5f  \n', ii, SS(ii))     ii=ii+1; end %% Version C. [while ... end] clearvars S N ii SS S=0; N=input('Enter number if series to compute:  '); ii=1; while ii~=N+1     if mod(ii,2)==0         S=S-1/ii;     else         S=S+1/ii;     end     SS(ii)=S;     fprintf('Sum of %g series is equal to %2.5f \n', ii, SS(ii))     ii=ii+1; end %% Version D. [while ... end] clearvars n N S SS sign=1; S=0; N = input('Enter number of series to compute:  '); n = 1; while n<N+1     S=S+sign/n;     SS(n)=S;     fprintf('Sum of %g series is equal to %2.5f \n', n, SS(n))     n=n+1;     sign=-sign; end %% Version E. [while ... end] clearvars SS ii S N S=0; N=input('Enter number if series to compute:  '); ii=1; while ii~=N+1 if mod(ii,2)==0         S=S-1/ii;         SS(ii)=S; else         S=S+1/ii;         SS(ii)=S; end     fprintf('Sum of %g series is equal to %2.5f \n', ii, SS(ii))     ii=ii+1; end

One of the easiest and straightforward approaches to preserving all values from all iterations is to initiate a new series of variables, e.g., SS(ii) and SS(n)s. When you are saving all values of calculated outputs within loops, it is salient to interpret SS(ii) and SS(n) correctly. For example, SS(1) first takes the value of S=1, and S = S-1/2 leads to SS(2) = 1-1/2 = ½. In the next step (step 2), S=S +1/3 leads to SS(3) =1/2+1/3 =5/6, and so forth.

Example 7

Compute the expression f (t) = esin(3t) t = 0 : 0.001 : 6.28; by employing [for ... end] and [while ...end] loop iteration operators and preserving all of the values from all iterations. From every iteration, one value of f (t) is saved, corresponding to each value of t.

%% Ex7_FOR_WHILE.m clearvars % Ver 1 ii =1; for t=0:.001:6.28     f(ii)=exp(sin(t));     ii=ii+1; end % Ver 2 t=0:.001:6.28; for k=1:numel(t)     f(k)=exp(sin(t(k))); end %% Ver 3 jj=0; while jj~=numel(t)     f(jj+1)=exp(sin(t(jj+1)));     jj=jj+1; end % Ver 4 m=1; while m~=numel(t)+1     f(m)=exp(sin(t(m)));     m=m+1; end

Note

It is salient to use f(ii) or f(k) or f(jj+1) or f(k) while computing f(t) within the [for ... end] and [while ... end] loops. This preserves all the values of f(t) from the iteration process with respect to the values of t. If only f is used instead of f(ii) or f(k) or f(jj+1) or f(k), then only one very last value of f(t) is saved.

One of the most common mistakes that users make is that while working with loop operators ([for ... end], [while ... end]), they overlook index (ii) or (k) or (jj) or (m) after the main variable. For example, f(ii), f(k), f(jj+1), and f(k) in the previous example collect all values from the whole iteration process.

Another most common mistake that users make is that while working with loop operators ([for ... end], [while ... end]), they assign wrong index values for (ii), (jj). For example, they use negative values or values starting with 0 or noninteger values or use mismatched sizes. In the previous example (version 3), we overlook assigning the value 0 to jj before the [while end] loop or assign jj=0 and at the same time assign f(jj). This is not acceptable. f(0) is meaningless for one important reason: a variable cannot have an index of 0. Indexes can be 1, 2,3, ... 1012, ...1025 + 1, ... but not ..., -3,-2, -1, 0 or 0.12, 2.1, 3.35, 5.5, 7/8, 100/899, etc.

There is a good alternative option or approach in collecting every value from every computation within a loop, which is to assign a new variable with an index. For example, this can be attained via the following:

%% Ex7_FOR_WHILE.m clearvars % Ver 1 ii =1; for t=0:.001:6.28     f=exp(sin(t));     F1(ii)=f;     ii=ii+1; end % Ver 2 t=0:.001:6.28; for ii=1:numel(t)     f=exp(sin(t(ii)));     F2(ii)=f; end %% Ver 3 jj=0; while jj~=numel(t)     f=exp(sin(t(jj+1)));     F3(jj+1)=f;     jj=jj+1; end % Ver 4 jj=1; while jj~=numel(t)+1     f=exp(sin(t(jj)));     F4(jj)=f;     jj=jj+1; end

It must be noted that in this example the best and most efficient computation approach is vectorization, as shown here:

t=0:.001:6.28 f=exp(sin(t));

Note

For the efficiency of computation processes or to improve your code performance, it is recommended you avoid using the [for ... end] and [while ...end] loop control statements whenever feasible. Instead of the loop iteration, it is recommended to employ the vectorization approach, as shown in Example 7: t=0:.001:6.28; f=exp(sin(t)).

Example 8

Let’s look at the famous “wheat and chessboard problem” story in this example. The problem is defined by the following: pieces of grain are placed in each chessboard square in the order of one grain in the first square, two pieces of grain in the second, four pieces of grain in the third, eight pieces of grain in the fourth, 16 pieces of grain in the fifth, 32 pieces of grain in the sixth, and so on, by doubling the pieces of grain on each subsequent square of the chessboard.

The sum of all grains to be placed on the chessboard is 1+2+4+8+16+32 ... and so forth. This can be also expressed as the sum of powers of 2: 20 + 21 + 22 + 23 + 24 + 25 + ...263 and is equal to 264 − 1 = 18,446,744,073,709,551,615. This is indeed a huge number of grains requested by the chess inventor for his ingenious invention of the chess game as a reward from a king. In simple calculations, if one grain weighs 0.025 grams, then the whole amount would weigh over 461 billion tons of grains. That would be a mountain of wheat grains bigger than Mount Everest. Let’s compute the number of grains using [for ... end] and [while ... end] loops.

% ChessInventorReward.m % Example: Grains of Wheat on the Chess Board %% Version A. [while ... end] loop clearvars S=1; Ncell=64; jj=1; while jj~=Ncell         S=S+2^jj; jj=jj+1; end display(['Number of cells: ', num2str(Ncell)]) display('& total sum of grains is: '), disp(uint64(S)) % Now test our results with a simple solution: 2^64-1; Error=S-2^64 %#ok %% Version B. [for ... end] loop clearvars S=0; Ncell=64; for ii=0:Ncell-1         S=S+2^ii; end display(['Number of cells: ', num2str(Ncell)]) display('& total sum of grains is: '), disp(uint64(S)) % Now test our results with a simple solution: 2^64-1; Error=S-2^64 %#ok

Both of the solution scripts output the same number of grains: 18,446,744,073,709,551,615 with 0 error. Note that 18,446,744,073,709,551,615 = 264 − 1 is the maximum length of any integer to be displayed correctly in MATLAB’s 64-bit version installed on a 64-bit processor computer.

Note

In this example, the most efficient way of computing the number of grains on the chessboard is the vectorization approach:

n=0:63; N = 2.^n; S = sum(N); disp(uint64(S))

Example 9

Prove that \( {\sum}_{k=1}^{\infty}\frac{1}{k^2}=\frac{\pi^2}{6} \). Compute this summation by using the [for ... end] and [while ... end] loops.

% SumPi6.m %% Example: sum(1/k^2)=pi^2/6 % Version A. [while...end] loop clearvars S=0; jj=1; k=input('Enter number of iterations to compute:  '); while le(jj, k)     S=S+1/jj^2; jj=jj+1; end display(['Number of cells: ', num2str(Ncell)]) display('& total sum of grains is: '), disp(uint64(S)) Error = (pi^2/6)-S; display(Error) % Example: sum(1/k^2)=pi^2/6 % Version B. [for ... end] loop clearvars –except k S=0; for jj=1:k     S=S+1/jj^2; end display(['Number of cells: ', num2str(Ncell)]) display('& total sum of grains is: '), disp(uint64(S)) Error = (pi^2/6)-S; display(Error)

Example 10

Prove that \( {\sum}_{n=0}^{\infty}\frac{{\left(-1\right)}^n4}{2n-1}=\pi \). Compute this summation by using the [for ... end] and [while ... end] loops.

%% Series_PI.m % [for .. end] clearvars N = input('Enter the number series to compute:   '); S = 0; for n = 1:N     S = S+(4*(-1)^(n+1))/(2*n-1); end fprintf('Sum of n = %d is series:  %1.5f \n', n, S) %% % [while .. end] clearvars N = input('Enter the number series to compute:   '); S = 0; n = 1; while n~=N+1   S = S+(4*(-1)^(n+1))/(2*n-1);   n=n+1; end fprintf('Sum of n = %d is series:  %1.5f \n', n, S)

Example 11

Prove that \( {\sum}_{n=0}^{\infty}\frac{1}{n!}=e \). In this exercise, the sum of rational factorial series is equal to the natural logarithm base e. Compute the sum of the series \( \frac{1}{0!}+\frac{1}{1!}+\frac{1}{2!}+\dots \frac{1}{n!}\dots =e \) by using the [for ... end] and [while ... end] loops.

%% Series_e.m % [for .. end] clearvars N = input('Enter the number series to compute:   '); S = 0; for n = 1:N     S = S+1/factorial(n); end fprintf('Sum of n = %d is series:  %1.5f \n', n, S) %% % [while .. end] clearvars N = input('Enter the number series to compute:   '); S = 0; n = 1; while n~=N+1   S = S+1/factorial(n);   n=n+1; end fprintf('Sum of n = %d is series:  %1.5f \n', n, S)

Note that in this exercise the function factorial() is employed. The most efficient way of computing the sum of these series is the vectorization approach: S = sum(1./factorial(1:N)).

Memory Allocation

When all values from all iterations are saved, it is recommended to employ memory allocation methods to improve the computation efficiency. Let’s analyze how the computation efficiency is enhanced by the memory allocation approaches. With the memory allocation technique, a user-specified memory is allocated to the computed variable with a user-specified size, and during the computation with a loop, all of the variable’s values are recorded in the prespecified memory. This speeds up the whole computation process considerably. With the memory allocation technique, the exact size of the variable being computed is created before the loop iteration, via the standard matrix/array generators (e.g., ones() or zeros()).

The general syntax/pseudocode of the memory allocation is as follows:

% [FOR ... END] M = zeros(1, n); for ii = 1:n M(ii) = [computation]; end % [WHILE ... END] MM = zeros(1, k); jj=1; while jj ~=k  MM(jj) = [computation];  jj=jj+1; end

This syntax can be applied to loops within loops. Let’s consider the memory allocation technique in the following examples.

Note

It is important to employ memory allocation techniques while using the [for ... end] and [while ... end] loops with considerable computations. This will decrease computation time and save computing resources.

Example 12

In the 17th century, Leibnitz used the series expansion of arctan(x) to find an approximation of π. By using the Maclaurin series formula, we can write it as follows:

$$ \mathit{\arctan}(x)\approx 0+(1)x+\frac{0}{2}{x}^2-\frac{2}{3!}{x}^3+\frac{0}{4!}{x}^4+\frac{0}{5!}{x}^5\dots =x-\frac{x^3}{3}+\frac{x^5}{5}-\frac{x^7}{7}+\frac{x^9}{9}\dots $$

Considering that \( (1)=\frac{\pi }{4} \) , we can substitute x = 1 into the previous expression and will get the following expression:

$$ \frac{\pi }{4}=1-\frac{1}{3}+\frac{1}{5}-\frac{1}{7}+\frac{1}{9}-\dots $$

That can be also written for N terms in this form:

$$ \frac{\pi }{4}\cong {\sum}_{k=0}^N\frac{{\left(-1\right)}^k}{2k+1}={S}_N $$

The task is to write a script that computes the sum (SN) of N terms, approximates the value of \( \frac{\pi }{4} \), and then plots the iteration process by computing the difference (error) \( Error=\frac{\pi }{4}-{S}_N \) using the [for ... end] and [while ... end] loops.

Here are possible solution scripts collected under one script called LeibnitzSeries.m to compute the Leibnitz series for an approximation of \( \frac{\pi }{4} \):

%% LeibnitzSeries.m % Version A. clearvars N=input('Enter number of terms to approximate pi/4:  '); S=0;               % Initial value of summation Err=zeros(1, N);   % Memory allocation for k=0:N-1     p=(-1)^k;     S=S+p/(2*k+1);     Err(k)=pi/4-S;  % Accumulates all of Errors from all iterations end plot(1:N, Err), grid on title(['\pi/4 Approximation of ', num2str(N), ' terms']) ylabel('Error'), xlabel('Number of terms') %% Leibnitz series % Version B clearvars n=input('Enter number of terms to approximate pi/4:  '); S=0;  % Initial value of summation Error=zeros(1, n);  % Memory allocation k=0; while k<=n-1     p=(-1)^k;     S=S+p/(2*k+1);     Error(k+1)=pi/4-S; % Accumulates all of Errors from all iterations     k=k+1; end plot(1:n, Error), grid on title(['\pi/4 Approximation of ', num2str(n), ' terms']) ylabel('Error'), xlabel('Number of terms')

If you execute the script with N=200 terms, you get the plot shown in Figure 2-3, which displays the results of series approximation.

Figure 2-3
A graph titled pie by 4 approximation of 200 terms plots error versus number of terms. The sine curves are taller on the left and extend linearly.

\( \frac{\uppi}{4} \) approximation by 200 terms of the Leibnitz series

It is also possible to have one loop within another. Let’s look at several examples to generate loops within loops with [for ... end] and [while ... end].

Note

It is also possible to make multiple nested [for ... end] loops.

Example 13

Create elements of a 5-by-7 matrix with pseudorandom integer numbers of 1 to 10. Here is the solution script Pseudo_Randi.m:

% Pseudo_Randi.m for k=1:5     for n=1:7         AB(k,n)=randi(10,1);     end end display(AB)

By executing the script, the following results are obtained:

AB =      3     5     3     6     4     8     6      2     1     5     6     7     2     9      9     6     8     1     9     4     9      4     9     9     4     7     3     3      3     7     2     8     8    10     8

Note that every time when the script is executed, different pseudorandom integers ranging within [1, 10] are generated. As demonstrated in the previous examples, the [for, end] and [while, end] loop control statements can be employed interchangeably.

For this exercise, the following is the [while .. end] loop-based solution script:

% [while .. end] k=1; while k~=5     n=1;     while n~=7         AB(k, n)=randi(10,1);         n=n+1;     end     k=k+1; end display(AB)

Note where the second loop’s iteration value n is assigned in the two nested [while .. end] loops.

Example 14

Compute the sum of the following series by using the [for ... end] and [while ... end] loop iterations: \( f\left({b}_n,x\right)={\sum}_{n=1}^{\infty}\frac{b_n\mathit{\sin}\left(\left(2n-1\right)\pi x\right)}{2L} \). Take n = 1 : 11, bn = [−5...5], x = [0...L], and L = 10. For x take a step size of \( \Delta x=\frac{L}{2000}. \) Plot all computation results.

Here is the solution script with the [for ... end] loop (Sine_Series.m):

% Sine_Series.m %% Ver A. [FOR ... END] clearvars, close all n=11; b = -5:5;x=0:.01:10; f=0; L=10; f = zeros(n, numel(x)); % Memory allocation for k=1:n     f=f+(b(k)*sin((2*k-1)*pi*x(:))/(2*L));     Fun(k,:)=f;     plot(x(:), Fun(k,:)), label{k}=(['Iteration: ' num2str(k)]);     legend(label{:}), hold all, end grid on, title('sum of series'), xlabel('x'), ylabel('f(b_n, x)') %% Ver B. clearvars n=11; b = -5:5;x=0:.01:10; L=10; f = zeros(n, numel(x)); % Memory allocation for k=1:n     f(k, :)=(b(k)*sin((2*k-1)*pi*x(:))/(2*L)); end Fun = sum(f(:,:));  % Obtain the final values (total sum of all).

An alternative solution script with the [while ... end] loop (see Figure 2-4). Using f(k,:) saves all values of the vector f(bn, x) in the order of calculation inside the loop.

%% Ver C. [WHILE...END] clearvars, close all n=11; b = -5:5;x=0:.01:10; f=0; L=10; k=1; Fun = zeros(n, numel(x)); % Memory allocation while k<n+1     f=f+(b(k)*sin((2*k-1)*pi*x(:))/(2*L));     Fun(k,:)=f;     plot(x(:), Fun(k,:)), label{k}=(['Iteration: ' num2str(k)]);     legend(label{:}), hold all     k=k+1; end grid on, title('sum of series'), xlabel('x'), ylabel('f(b_n, x)')

Figure 2-4
A graph plots f of b subscript n, x versus x for iterations 1 to 11. The overlapped curves have identical lengths of the crest and troughs and identical wavelengths.

Sum of series: f(bn, x)= \( {\sum}_{n=1}^{\infty}\frac{b_n\mathit{\sin}\left(\left(2n-1\right)\pi x\right)}{2L} \)

An alternative and best solution in terms of computational efficiency using vectorization approach with meshgrid() is as follows:

%% Ver D. Vectorization and No loop clearvars, close all n=11; b = -5:5;x=0:.01:10; L=10; k=1; [bS, xS] = meshgrid(b,x); [~, nS] = meshgrid(x, 1:n); f = (bS.*sin(pi*(transpose(2*nS-1)).*xS)/(2*L)); plot(x, cumsum(f.')) L = cell(n,1); for ii=1:n     L{ii}=strcat('n = ', num2str(ii)); end legend(L) grid on, title('sum of series'), xlabel('x'), ylabel('f(b_n, x)')

Note that the commands related to plot building, such as plot(), label{}, and legend(), do not have an effect on the accuracy of the calculations. But they considerably slow down the computation process. Therefore, it is advisable to avoid plotting the computed data within loops if possible.

Example 15

Compute the values of the function \( F\left(\mu, t\right)=\mathit{\sin}\ (2t)\ast \sqrt{\mathit{\sin}\ \left(\mu t\sqrt{t+{t}^2+{t}^3}\right)\ } \) for t = 0...π (∆t = π/1000) and μ = 1...7 by using the [for ... end] and [while ... end] loop operators.

Here is the plain script (F_Series.m) with two loop operators:

% F_Series.m %% [FOR ... END] mu=1:7; t=0:pi/1e3:pi; F=zeros(numel(mu), numel(t)); % Memory allocation for mu=1:7     for ii=1:numel(t)     F(mu, ii)=sin(2*t(ii))*sqrt(sin(mu*t(ii)*sqrt(t(ii)+t(ii)^2+t(ii)^3)));     end     plot(t, F(mu,:)), hold all end xlabel('t'), ylabel('F'), title('Sine waves'), grid on %% [WHILE ... END] mu=1:7; t=0:pi/1e3:pi; F=zeros(numel(mu), numel(t)); % Memory allocation MU = 1; while ne(MU, 8)     ii=1;     while ii~=numel(t)+1     F(MU, ii)=sin(2*t(ii))*sqrt(sin(MU*t(ii)*sqrt(t(ii)+t(ii)^2+t(ii)^3)));     ii=ii+1;     end     plot(t, F(MU,:)), hold all     MU=MU+1; end xlabel('t'), ylabel('F'), title('Sine waves'), grid on

Both iteration loops produce identical solutions and an identical plot figure, as shown in Figure 2-5. While simulating this script, there will be complex outputs from the square root of negative values as well. Therefore, some warning messages will be displayed in the Command window indicating omitted/ignored imaginary components in the plot shown in Figure 2-5.

Figure 2-5
A line graph titled sine waves plot F versus t. The graph plots several overlapping full cycle sine curves.

Plot of \( F\left(\mu, t\right)=\mathit{\sin}\ (2t)\kern0.5em \ast \sqrt{\mathit{\sin}\ \left(\mu t\sqrt{t+{t}^2+{t}^3}\right)\ } \) for t = 0...π (∆t = π/1000), μ = 1...7

Example 16

Compute \( f(t)={e}^{\frac{-3t}{7}} \) function values for t = 0...5 with a time step of ∆t = 10−6 and ∆t = 10−3, and plot computed function values against time values. The very small time step ∆t = 10−6 is taken to demonstrate the importance of memory allocation and loop iteration versus vectorized calculations, and ∆t = 10−3 is taken to show the importance of where to put the plot() command while using loop iterations [for ... end] and [while ... end].

There are four different ways (combined into one script EXP_Calcs.m) of solving the given exercise with [for, end] and [while, end] loop control statements. All of the four ways produce identical results, but their computation (elapsed) time differs substantially. Note that in this exercise, [for, end] and [while, end] loop control statements are used for demonstration purposes only to explain how to employ loop statements and to improve their efficiency. By default, for this type of exercise or any other vector computations, the direct computation of vector values of f(t) is much more efficient than using loop statements.

% EXP_Calcs.m computes Exp(-3t/7) Math function % Solution method 1 clc; clear all; close all tic t=0:1e-6:5; m_num=length(t); for m=1:m_num     f(m)=exp(-3*t(m)/7); end Tfor=toc; fprintf('[1] FOR loop computation TIME: %g \n', Tfor) plot(t, f, 'ro'), xlabel('t'), ylabel('f(t)'), title('t vs. f(t)') % % Solution method 2 clearvars, close all tic t=0:1e-3:5; m_num=length(t); for m=1:m_num     f(m)=exp(-3*t(m)/7); plot(t(m), f(m), 'ro'), hold end TforP=toc; xlabel('t'), ylabel('f(t)'), title('t vs. f(t)') fprintf('[2] FOR loop computation TIME with plot() in it: %g \n', TforP) % Solution method 3 clearvars, close all tic t=0:1e-3:5; m_num=length(t); m=1; while m<=m_num     f(m)=exp(-3*t(m)/7); plot(t(m), f(m), 'ro'), on     m=m+1; end Twhile=toc; xlabel('t'), ylabel('f(t)'), title('t vs. f(t)') fprintf('[3] WHILE loop computation TIME with plot() in it: %g \n', Twhile) % Solution method 4. Improved by memory allocation. clearvars, close all tic t=0:1e-6:5; m_num=length(t); f=zeros(1,m_num-1); for m=1:m_num     f(m)=exp(-3*t(m)/7); end plot(t,f, 'bo'); TforIm=toc; xlabel('t'), ylabel('f(t)'), title('t vs. f(t)') fprintf('[4] Improved FOR loop TIME with memory allocation: %g\n', TforIm) % Solution method 5. Vectorized method clearvars, close all t=0:1e-6:5; tic f=exp(-3*t/7); Tvec=toc; plot(t, f, 'bo') xlabel('t'), ylabel('f(t)'), title('t vs. f(t)') fprintf('[5] Recommended VECTORIZED method time: %g\n', Tvec)

By executing the previous script (EXP_Calcs.m) in a personal computer (processor: Intel COREi7, RAM: 16GB, OS: Windows 10, in MATLAB R2022a), the following computation time results are obtained in the Command window. Note that the plot figure is not shown here.

[1] FOR loop computation TIME: 0.533504 [2] FOR loop computation TIME with plot() in it: 13.4151 [3] WHILE loop computation TIME with plot() in it: 13.1509 [4] Improved FOR loop TIME with memory allocation: 0.244569 [5] Recommended VECTORIZED method time: 0.0175538

From the simulation results, the influence of the plot() command on the computation time within [for, end] and [while, end] control loops is demonstrates once more. In this plain example, it is clear how much CPU time (~17.5 times more time) is spent on plotting the computed data in solutions 2 and 3 than in solutions 1 and 4 even though the step size ∆t = 10−3 is chosen to be 103 larger than the one (∆t = 10−6) used with the three other ways. The simulation speed difference between the [for .. end] loop (way 1) and vectorization (method 5) is more than 30 times. In other words, the speed of the calculation with the [for ... end] loop is slower than the vectorization approach for more than 3000 percent.

Note

If it is possible, avoid using the plot() command within the [for...end] and [while ... end] loops to enhance the computation/simulation time efficiency.

The memory allocation is necessary whenever the use of [for, end] and [while, end] loop control statements is unavoidable. By using memory allocation techniques, you can improve the time efficiency of loop control statements substantially. In the previous simple example, the computation time has been improved more than 2.18 times by using a memory allocation technique (method 1 versus method 4). It must be noted that the time efficiency with a memory allocation technique can be observed if the number of iterations is considerably large, for instance, several thousand iterations or beyond. The vectorization approach is indeed superior. If method 4 with memory allocation is compared with the vectorized approach (method 5), the vectorization is more than 13 times faster than memory allocation method for computations of this example.

Note

If the computation/simulation problem requires using the [for...end] and [while ... end] loops, use the memory allocation technique to enhance the computation/simulation time efficiency.

To calculate elapsed (computation) time, stopwatch timer [tic ... toc] operators are recommended to track the computation time of a script. In fact, there are several other alternative operators as well in MATLAB that count elapsed (computation) of a script (code) or function file. They are [cputime] and [clock, etime]. These operators can be used as follows within M-files. This is the comparative analysis script (EXP_CT.m) of these operators with the previous studied example to compute \( f(t)={e}^{\frac{-3t}{7}} \) function values for t = 0...5 with a time step of ∆t = 0.0001.

% EXP_CT.m %% [tic ... toc] clc; clear all, close all T1=tic; t=0:1e-4:5; m_num=length(t); for m=1:m_num     f(m)=exp(-3*t(m)/7); end Tfor1=toc(T1); fprintf('FOR loop time [tic...toc]: %g \n', Tfor1) %% [cputime ... cputime-Time] clear all, close all TT=cputime; t=0:1e-4:5; m_num=length(t); for m=1:m_num     f(m)=exp(-3*t(m)/7); end Tfor2=cputime-TT; fprintf('FOR loop time with [cputime]: %g \n', Tfor2) %% [clock ... etime()] clear all, close all TT=clock; t=0:1e-4:5; m_num=length(t); for m=1:m_num     f(m)=exp(-3*t(m)/7); end Tfor3=etime(clock, TT); fprintf('FOR loop time with [clock...etime]: %g \n', Tfor3)

By executing the previous script, the following results are obtained in the Command window:

FOR loop time [tic...toc]: 2.49076 FOR loop time with [cputime]: 2.46482 FOR loop time with [clock...etime]: 2.494

The simulation results show that these operators work similarly and produce very close numerical results. In addition to these operators, there is another operator called [timeit] that can be also employed to compute the overall computation time spent for all simulation processes of function files. This operator was introduced with MATLAB R2014b.

The [break] command is a powerful and handy operator that is used mainly within [while, end] and [for, end] loop control statements to halt the evaluation process when certain conditions are met. This is another technique to improve iteration time efficiency. Let’s look at the [break] command’s implementation in the following example.

Example 17

Let’s compute the Fibonacci numbers. The Fibonacci sequence is defined by the following expressions: f1 = 1, f2 = 1, f3 = f1 + f2, ..., fn = fn − 2 + fn − 1.

Thus, if f1 = 1, f2 = 1, f3 = 3, f4 = 3 + 1, f5 = 4 + 3, ..., then do the following:

  1. 1)

    Show the first 13 elements of the Fibonacci sequence.

  2. 2)

    Compute the first 111 elements of the Fibonacci sequence or stop the iteration when the sequence has reached the value of 123456789.

Here is the solution script (Fibonacci.m). It computes the first 13 elements (series) with [for ... end] and [while ... end], and 111 elements (series) of the sequence or halts the computation if the sequence reaches to 12345789 by employing the [break] operator.

% Ver 1. Computation of 13 elements of the Fibonacci Numbers: [for ... end] clearvars f(1) = 1; f(2)=1; f = [f(1), f(2), zeros(1, 11)]; % Memory allocation fprintf('Element: %.0f  FN: %.0f \n', 1, f(1)); fprintf('Element: %.0f  FN: %.0f \n', 2, f(2)); for jj=3:13     f(jj)=f(jj-2)+f(jj-1);     fprintf('Element: %.0f  FN: %.0f \n', jj, f(jj)); end %% Ver 2. Computation of 13 elements of the Fibonacci Numbers: [while...end] clearvars f(1) = 1; f(2)=1; jj=3; f = [f(1), f(2), zeros(1, 11)]; % Memory allocation fprintf('Element: %.0f  FN: %.0f \n', 1, f(1)); fprintf('Element: %.0f  FN: %.0f \n', 2, f(2)); while jj<=13     f(jj)=f(jj-2)+f(jj-1);     fprintf('Element: %.0f  FN: %.0f \n', jj, f(jj));     jj=jj+1; end %% [BREAK]. Iteration of the Fibonacci Numbers is controlled by [BREAK] clearvars F(1) = 1; F(2) = 1; F = [F(1), F(2), zeros(1, 40)]; % Memory allocation fprintf('Element: %.0f  FN: %.0f \n', 1, F(1)); fprintf('Element: %.0f  FN: %.0f \n', 2, F(2)); for ii=3:111     F(ii)=F(ii-2)+F(ii-1);     fprintf('Element: %.0f  FN: %.0f \n', ii, F(ii));     if F(ii)>=123456789     fprintf('Iteration is halted because \n ')     fprintf('the last computed value is greater than 123456789 \n')     break     else         continue     end end

This script produces the following output in the Command window:

Element: 1  FN: 1 Element: 2  FN: 1 Element: 3  FN: 2 Element: 4  FN: 3 Element: 5  FN: 5 Element: 6  FN: 8 Element: 7  FN: 13 Element: 8  FN: 21 Element: 9  FN: 34 Element: 10  FN: 55 Element: 11  FN: 89 Element: 12  FN: 144 Element: 13  FN: 233

The results from version 2 are identical to the results from version 1, and thus, they are not shown here. Here are the results from the previous section of the code with the [break] operator:

Element: 1  FN: 1 Element: 2  FN: 1 Element: 3  FN: 2 Element: 4  FN: 3 Element: 5  FN: 5 Element: 6  FN: 8 Element: 7  FN: 13 Element: 8  FN: 21 Element: 9  FN: 34 Element: 10  FN: 55 Element: 11  FN: 89 Element: 12  FN: 144 Element: 13  FN: 233 ... Element: 25  FN: 75025 Element: 26  FN: 121393 Element: 27  FN: 196418 ... Element: 39  FN: 63245986 Element: 40  FN: 102334155 Element: 41  FN: 165580141 Iteration is halted because  the last computed value is greater than 123456789

Note that in the previous section with the [break] operator, the memory allocation operation F = [F(1), F(2), zeros(1, 40)] creates [1, 1, 40 elements of 0]. Therefore, after 41 iterations, the last element (42nd element) of F remains 0.

Example 18

Let’s compute the values of the sine function h(θ) =  sin (θ) for θ = 0...2π with 1,000 incremental steps and stop computation when the value of the function h(θ) ≈ 0.9999.

The sine function fluctuates between 0 ... 1; 1...0; 0...-1; -1...0 for θ = 0...2π; therefore, you should stop the computation loop when the function value reaches 0.9999. Here is the solution script (SINE.m) that computes and halts the computation process with a [break] statement when the preset condition is met:

% SINE.m computes sin(theta) clearvars theta=linspace(0, 2*pi, 1000); k=length(theta); h=ones(1,k-1); for ii=1:k     h(ii)=sin(theta(ii));     data(ii,:)=[theta(ii);h(ii)]; if abs(h(ii))>=0.9999     fprintf('Computation is halted after %g iterations\n', ii);     fprintf('The function value is: %1.5f \n', h(ii)) fprintf('When theta is equal to % 1.5f degrees\n', theta(ii)*180/pi) break else continue end end plot(data(:,1), data(:,2), 'bd'), hold on plot(data(ii,1),data(ii,2), 'p', 'markerfacecolor','c',  'markersize', 18) grid on

When the script (SINE.m) is executed, the following output is displayed in the Command window:

Computation is halted after 249 iterations The function value is: 0.99994 When theta is equal to  89.36937 degrees

Figure 2-6 shows the plot.

Figure 2-6
A line graph plots a concave down increasing curve from the origin.

Plot of h(θ) =  sin (θ) for \( \uptheta =0\dots \frac{\uppi}{2} \) and computation halted at h(θ)=0.9999

This solution script can be also edited or rewritten with [while, end] in a similar way. That is left as an exercise for you to try for self-testing purposes.

Example 19

Write a script file with the [for ... end] loop and conditional statements [if, elseif, else, end] to compute the values of the function. Then plot the computed values.

$$ f(t)=\left\{\begin{array}{c}{e}^{-2{t}_1}+100{t}_1,\kern1em {t}_1\le -13\kern1.75em \\ {}\cos \left(100{t}_2\right)-\sin \left(10{t}_2\right)-3\ge {t}_2\ge -13\\ {}\cos \left(100{t}_3\right)+{e}^{t_3},\kern0.75em -3\le {t}_3\le 0\\ {}1,\kern1.5em {t}_4>0\kern0.5em \end{array}\right. $$

For the values of t ∈ [−4π, 3π], take ∆t = 0.0001.

Here is the solution script (Fun_Sets.m):

%% Fun_Sets.m clc, clearvars t=-4*pi:.0001:3*pi;  % Whole t series F=ones(size(t));     % Memory allocation tic; for ii = 1:numel(t)     if t(ii)<=-2*pi         F(ii)=exp(sin(2*t(ii)))+exp(cos(100*t(ii)));     elseif t(ii)>-2*pi && t(ii)<=pi         F(ii) = sin(2*t(ii))+cos(100*t(ii));     elseif t(ii)>pi && t(ii)<=2*pi         F(ii)=exp(sin(100*t(ii)))+exp(cos(2*t(ii)));     else         F(ii)=1;     end end    Tma=toc;    plot(t, F), grid on;    plot(t, F), grid on, xlabel('\it t'), ylabel('\it F(t)'),    title('Plot of function values w.r.t value ranges of t'), shg    fprintf('Computation Time with memory allocation:  %2.6g \n', Tma)

Here are the outputs in the Command window and plot figure of the script (Fun_Sets.m). Figure 2-7 shows the plot figure of the script.

Computation Time with memory allocation:  0.0286769

Figure 2-7
A line graph plots F of t versus t. The graph plots sinusoidal curves for negative (13, 1.5), (4, 1), and (6, 5.4). Values are approximated.

Plot of the function \( f(t)=\left\{\begin{array}{c}{e}^{-2{t}_1}+100{t}_1,\kern1em {t}_1\le -13\kern1.75em \\ {}\mathit{\cos}\left(100{t}_2\right)-\mathit{\sin}\left(10{t}_2\right)-3\ge {t}_2\ge -13\\ {}\mathit{\cos}\left(100{t}_3\right)+{e}^{t_3},\kern0.75em -3\le {t}_3\le 0\\ {}1,\kern1.5em {t}_4>0\kern0.5em \end{array}\right. \)

One of the tricky points in the previous example is separating out the four value ranges of t according to the problem statement and then computing four separate function values. The loop operation [for ... end] before the conditional statements [if... elseif... elseif... elseif ... else ... end] perform the whole computation with respect to the indexes of t, whereas [if... elseif... elseif... elseif ... else ... end] will separate out the values of t by comparing every value of t(ii) according to the given conditions. In this case, the index (ii) is mandatory.

Symbol References in Programming

In MATLAB, there are dozens of important symbols used for various purposes in different contexts of code. The symbol references are discussed in the following sections.

Asterisk

In general, the symbol * is used for the multiplication operator, but in other instances, it can be used as a wildcard for file name identification. For instance, if you need to delete all files (MATLAB’s autosave files of M/MLX-files) with a file extension of *.asv, the following command performs the task:

>> delete *.asv

In this way, you can delete all the files with the file extension of *.asv located in the current directory of MATLAB. Another example is if you need to locate an M-file called midpoint_rule.m, then you can type part of the file name as so:

>>  dir('midp*.m') midpoint_rule.m

Also, you can use * to get information on variables residing in the workspace by typing part of their names or delete them by typing part of their names, for instance:

>> whos >> who Your variables are: H   N    NaH  NbN  NN  Nn  NCN  NkN >> clear N*    % All variables whose names start with N will be deleted from the Workspace >> whos         % Check which variables left in the Workspace   Name      Size            Bytes  Class     Attributes   H         5x1              3525  struct

At Sign

The @ sign/operator is mostly used to construct a function handle. Here’s an example:

F=@(argument lists)expression

Moreover, the @ operator is used to assign a new MATLAB class directory designator used to override MATLAB files. Here’s an example:

\@myclass\myfun.m

Note that MATLAB classes can be used to define object-oriented designs, which are not discussed in this book.

Colon

The colon (:) operator is used to generate a sequence of numbers or elements of arrays or assign indices. Here’s an example:

>>M=1:3:300; >>N=1:200; >>K=[N(1:10); M(1:10)]; >>Knew=K(1,:) Knew =      1     2     3     4     5     6     7     8     9    10

Note that when you use the colon to generate a sequence of numbers by specifying the step size, the last element of the being generated sequence may not match with the specified last element. For example, A = 1:3:20 generates A = [1 4 7 10 13 16 19], and B = 1:3:21 generates B = [1 4 7 10 13 16 19].

Comma

The comma (,) operator is used to separate variables or elements of arrays and indices, function input and output arguments, commands, or statements. Here’s an example:

>> M, N,K >> K(1,2) >> G=@(t, x) sin(x*t) >> for ii=1:2:20, Knewm(:)=K(1, ii)*2, end

Curly Brackets

The { } are used to assign or construct cell arrays and write fractions, superscripts, and subscripts via the LaTeX interpreter in plot figure titles and axis labels. Here’s an example:

>> KnM=[{Knew}, {K}, {N},{M}]; >> title('$sin(\frac{2\phi}{5})$','interpreter', 'latex'); >> xlabel('t_{at}'); >> ylabel('F^{dot}')

Dollar Sign

The $ is used mostly in expressing fractions via the LaTeX interpreter in plot figure titles and axis labels. Here’s an example:

>> ylabel('$\Omega(\frac{2\beta}{\alpha})$', 'interpreter', 'latex')

Dot

The . operator is used to add fields to an existing structure field, table variable name specifier, and object method specifier. It is used for decimal digits and element-wise matrix operations. Here’s an example:

>> MH=H(1,1).bytes >> P = [-3.1416, -1.5708, 0, 1.5708, 3.1416]; >> A = P.^2;

Dot-Dot

The two dots (..) operator is used to refer in sequence to the current directory. For instance, the following commands jump up one and two directories (if they already exist) from the current one:

>>cd ..\Fax >>cd ..\..\Desktop

Dot-Dot-Dot (Ellipsis)

The three dots operator (...) is a line continuation operator. Here’s an example:

>>  KmN=[1,2; ... 3,2; ] KmN =      1     2      3     2 >> fprintf('This is what you have entered: %f\n', ... KmN) This is what you have entered: 1.000000 This is what you have entered: 3.000000 This is what you have entered: 2.000000 This is what you have entered: 2.000000

Parentheses

The () are mostly used for indexing of array elements or specifying arguments passed to a called function. Here’s an example:

>> K(3, 4) >> F=@(x, y)sqrt(x.^2+y.^2) >> [m, n]=myFUN(x, y, k)

Percent

The % operator is one of the most commonly used reference symbols in MATLAB programming. It is used for five main purposes, of which four are for commenting purposes:

  • To assign comments within M-files (%)

  • To create cell modes with double percent signs (%%) and then leave a space

  • To assign conversion specifiers when used within fprintf() and sprintf()

  • To assign a block of comments when used with curly braces, %{, opened in one line and, %}, closed in another

  • To remove (%#ok) a warning sign to display computation results in the Command window

Let’s look at several examples for the % sign:

% This script is used for ... % Created by ... %% New cell mode starts from here ... fprintf('you have entered %g which is EVEN number \n', N) sprintf('you have entered %g which is EVEN number \n', N) X1=sprintf('Root2 of the equation is x1= %g*i', x1); %{  Start comments and remarks...  This script is used for....  Created by ...  Define entered integer type  End comments and remarks... %} K=randi(100,3); M=K*2.2        %#ok

Note

When using % with { } to insert comments in your script, the %{ open bracket must be on a separate line before the starting comments, and the %} closing must be at the end of the comments block on a separate line.

Semicolon

The ; is mainly used to construct arrays, suppress output display in the Command window, and separate commands entered on one line. Here’s an example:

>>K=[1 2; 3,4]; >> clear all; close all; clc

Single Quotes

Single quotes (' ') are one of the most commonly used reference symbols of MATLAB. They are used as character and string constructors and with the inline function. Here’s an example:

>> a=input('Enter value of a: '); >> Hurray = 'Today is a great DAY ! ' >> F_1 =inline('2*x^2-3*x+13')

Note the single quote (') is also used for a matrix transpose operation:

>> A = [1, 2; 3, 4] A =      1     2      3     4 >> A' ans =      1     3      2     4

Slash and Backslash

The / \ characters are used to separate elements of a path or directory string. Note that these characters are also used for division (\ for left matrix division) operations, and \ is used to write Greek letters in the LaTeX format. Here’s an example:

>> dir(['..\Circle13.m']) % Path or directory >> title(' \alpha(\theta) vs. \Omega(\theta)')  % LaTeX interpretation >> C = [2, 3, 4]; D=A/2;        % Division >> A = [2 3; 3 4]; b = [1;2]; x = A\b;  % Backslash or left matrix divide

Square Brackets

The square brackets ([ ]) are used to construct, declare, and concatenate arrays, and to declare and capture values returned by functions. They are also used to indicate text and labels in plot figures. Here’s an example:

>> K=[1 2; 3,4]; >> B=[K, K*2; rand(2,2), eye(2)]; >> [xout yout] = myfunction(z, t); >> gtext(['End point: ' num2str(yout(end)) ' [m]'], 'background', 'y');

For more information on MATLAB symbol references, see the appendix.

Function Files

Function files are a remarkable strength of the MATLAB package for efficient code generation and computations. Once the function files are saved, they will have the symbol ; M-files will have the symbol , and MLX-files will have symbol . The way the function files are executed and the way their simulation results are obtained are substantially different from M- and MLX-files.

First, let’s address why function files are necessary. The main reasons for using function files is that they are faster, are computationally more efficient, and consume less space in the workspace. Moreover, they can be called and executed within any M or MLX-files and the Command window. Function files are powerful and flexible and can be used for various purposes. They can be used not only to evaluate mathematical functions or perform calculations, but also to evaluate, compare and assess already evaluated data inputs as arguments. The general syntax and structure of the function file can be expressed in the following way:

function [A, B, ..., W] = FCN_name(a, b, ..., w) % Help. .... .... end

where [A, B, ..., W] are output variables and (a, b, ..., w) are input variables, also called input arguments. Note that function files have to start with the word function and the file name of the function file has to match with the word FCN_name in the previously shown example. In other words, the previous function file has to be named FCN_name.m. Otherwise, you cannot execute it. MATLAB automatically recognizes the function file as soon as you type in the word function and prompts you for the function file name when you save it the first time. Moreover, it is advised and required to end the function file with the keyword end. Naming the function files is like naming any M- or MLX-files. They have to start with a letter and must not contain any empty spaces or symbols except for an underscore, _.

In addition, some additional comments (help comments explaining how to use the function file) can be added to the existing function files by opening and editing them.

Note

One of the most common mistakes while recalling the function files is misspelling the name of the file.

In recent versions of MATLAB, function files can have different file names and function names. For example, a function file can be called MY_fun, but its script may be written as: function [Out1, Out2, ...] = fun(In1, In2, ...). This will not cause any error. However, it is recommended to have the same file name and function name.

In more recent versions of MATLAB, the function file syntax (called subfunctions/member functions) can be implemented/embedded within M-files and called/executed as part of M-files.

The function files can be created for various purposes, for instance, to perform computations or display simulation results. The function files can be created/written in several ways.

  • By using M-file or MLX-file editors or also using the Notepad text editor.

  • By using the main menu and selecting or from the drop-down option. The latter option of Live Function is available only starting from MATLAB 2018b.

  • By using the Symbolic MathFootnote 2 toolbox’s symbolic object identifier, syms.

When using the first way, you type in the function file and save a precisely matched function name with a file extension of *.m or *.mlx. It will be recognized by MATLAB automatically as a function file. When using the second and third ways, the editors will automatically generate the standard syntax components of the function file. The file can be edited without having to type in standard parts.

Let’s look at several examples to demonstrate how to create function files and work with them.

Example 1

Write a function file to compute \( f(t)=\frac{3}{e^{\mathit{\sin}(t)}}+\frac{5}{e^{\mathit{\cos}(t)}} \) and plot the computed values. This can be implemented as shown in the following script called myfunction.m. It uses the first way of creating the function file.

function f=myfunction(t) % HELP: this function file (myfunction.m) computes values of the expression: %{ f(t)=3./exp(sind(t))+5./exp(cosd(t)) for given values of t, saves the computed values of f(t) in the workspace, and plots computed resultsthem. Note that [t] is input argument that has to be in degrees not in radians, e.g., numerical array, e.g., >> t = -360:720360; To execute this file: >> t = -720:10:720;  f=myfunction(t); that assigns output values to a variable f and shows the plot. To execute this file: >> t = 0:1:180;  myfunction(t);  that assigns output values to a variable ans shows the plot. To execute this file: >> FF=myfunction(-180:2:360);  that assigns output values to a variable FF shows the plot. %} f=3./exp(sind(t))+5./exp(cosd(t)); plot(t, f, 'ro-', 'linewidth', 1.5), grid on title('Plot of myfunction.m file') end

It is good practice to have some comments in the function files specifying the functionality of the function file, specifics about input arguments, help hints how to use it with example input data, and so forth. When there are help comments in function files, users can search for help about function files from the Command window. They do so by recalling a function file name with the help command, as shown here:

>> help myfunction   HELP: this function file (myfunction.m) computes values of the expression f(t) = 3./exp(sind(t))+5./exp(cosd(t)) for given values of t, saves the computed values of f(t) in the workspace, and plots computed results them.   Note that [t] is input argument that has to be in degrees not in radians, e.g.numerical array, e.g. >> t = -360:720360;   To execute this file: >> t = -720:10:720;  f=myfunction(t);  % that assigns output values to a variable f     % and shows the plot.   To execute this file: >> t = 0:1:180;     myfunction(t);  % that assigns output values to a variable ans % shows the plot.   To execute this file: >> FF=myfunction(-180:2:360);  % that assigns output values to a variable FF           % shows the plot.

Note that to call and use the created function files, the function files must reside in the current (active) MATLAB path directory. Or, you must add the path (directory) where the function file is residing to the search directory of MATLAB. You can do that using the addpath(' ') command and specifying the directory inside (' '). If the function file’s directory (path) is not in the current directory or is not added to the list of the MATLAB paths, it cannot be recalled and executed. Subsequently, you’ll get error messages indicating an undefined function or variable.

Simulation of the previous function file (called myfunction.m) can be done from the Command window or within another M-file with an input variable of t:

>> % If the output variable is not specified, "ans" will be the default variable name. >> % That has all values of "f" of the function file. >> myfunction(0:2:720);  % The input argument "t" values are defined directly. >> t=0:2:720; f=myfunction(t); % Input and output variables are defined and given.

A second way of creating a function file is by clicking the main menu and selecting or . The following function file will be opened with a default name of untitled.

This file is opened with the button in the M-file editor.

function [outputArg1,outputArg2] = untitled(inputArg1,inputArg2) %UNTITLED6 Summary of this function goes here %   Detailed explanation goes here outputArg1 = inputArg1; outputArg2 = inputArg2; end

This one is opened with the button in the MLX-file editor.

Brief summary of this function. Detailed explanation of this function. function z = Untitled(x, y) z = x + y; end

The following example explains how to employ the third way of creating the function files.

Example 2

Given: \( f\left({u}_1,{u}_2\right)=\left\{\begin{array}{c}{u}_2-{e}^{2{u}_1}\\ {}1.25{u}_1-{e}^{3{u}_2}\end{array}\right. \)

A third way of creating a function file is to employ Symbolic MathFootnote 3 toolbox’s symbolic object identifier syms. The MATLAB tool matlabFunction creates an anonymous function file to compute f(u1, u2) with input arguments of u1, u2.

syms u1 u2         % Define variables (input data names) % Formulate the given function equations f=[u2-exp(2*u1), 1.25*u1-exp(3*u2)]; % Define a function file name, e.g. myFUN matlabFunction(f, 'file', 'myFUN');

When you execute these commands, a function file called myFUN.m is created in the current MATLAB directory.

function f = myFUN(u1, u2) %MYFUN % F = MYFUN(U1,U2) % This function was generated by the Symbolic Math Toolbox version 5.9 %    15-Apr-2022 14:20:01 f = [u2-exp(u1.*2.0),u1.*(5.0./4.0)-exp(u2.*3.0)];

Note that once a function is created with matlabFunction, you should not reuse this function tool to re-create the already created function file. If you try to do so, error messages will pop up. Another salient point in employing the matlabFunction tool is that this tool cannot generate function files containing variables with indexes, and if there are variables with indexes, the matlabFunction tool prompts you with errors.

Certain operations, commands, computations, or execution of several function files can be performed within the function file without any input arguments or outputs. A general syntax of such function files without any input arguments and output variables is very simple.

function functionNAME % ...

Let’s now look at the following example.

Example 3

Create a function file that clears all previously typed in commands from the Command window and displays benchmarking results of your computer. This getREADY.m function file performs the assigned tasks without any input arguments and any output data:

function getREADY % HELP. getREADY.m % This function file cleans up command history of MATLAB  and % performs benchmarking calculations of several MATLAB functions (LU, FFT, % ODE, etc.) installed computer against some of the computer configurations of the date. clc; close all; bench end

Note

There are two cases when the function files can be executed with the Run button from the M/MLX-file editor. (1) If the function file has no input arguments, (2) if the function file has a varying number of input arguments.

Example 4

Create a function file that computes the roots (x1, x2) and discriminant (D) of the quadratic equation ax2 + bx + c = 0 with respect to the input arguments of a, b, c, which are scalars. This function file (called QUAD.m) will produce three output variables according to the three input arguments.

function [x1, x2, D]=QUAD(a, b, c) % QUAD.m % Solves quadratic equations based on coefficients of: a, b, c % Note that a, b, c need to be scalars. fprintf('Solve: (%g)x^2+(%g)x+(%g)=0\n', a,b,c) D=b^2-4*a*c; % Roots x1=(-b+sqrt(D))/(2*a); x2=(-b-sqrt(D))/(2*a); if lt(D,0)     fprintf('This equation does not have real value roots!\n');     fprintf('Because discriminant is negative. D = %g\n', D);     fprintf('Complex Root1: x1= %10s\n', num2str(x1));     fprintf('Complex Root2: x2= %10s\n', num2str(x2)); elseif eq(D,0)     disp('This equation has one unique root! ');     disp('Because discriminant is zero. D=0 ');     fprintf('This equation has one unique root! \n');     fprintf('Because discriminant is zero. D=0 \n');     fprintf('Unique Root: x = %g \n', x1); else     fprintf('This equation has two roots \n');     fprintf('Because discriminant is: D = %g \n', D);     fprintf('Root1 of the equation is: x1= %g \n', x1);     fprintf('Root2 of the equation is: x2= %g \n', x2); end

Let’s test this function file with different input arguments and obtain the output variables from the Command window.

>> a=1; b=2; c=3; >> [x1, x2, D]=QUAD_01(a, b, c)     % Case 1. The values of a, b, c are predefined Solve: (1)x^2+(2)x+(3)=0 This equation does not have real value roots! Because discriminant is negative. D = -8 Complex Root1: x1= -1+1.4142i Complex Root2: x2= -1-1.4142i x1 =   -1.0000 + 1.4142i x2 =   -1.0000 - 1.4142i D =     -8 >> [x1, x2, D]=QUAD_01(1, 2, 3)   % Case 2. The values of a, b, c are entered directly Solve: (1)x^2+(2)x+(3)=0 This equation does not have real value roots! Because discriminant is negative. D = -8 Complex Root1: x1= -1+1.4142i Complex Root2: x2= -1-1.4142i x1 =   -1.0000 + 1.4142i x2 =   -1.0000 - 1.4142i D =     -8 >> [x1, x2, D]=QUAD_01(b, c, a)  % Case 3. The values of a, b, c are mixed up Solve: (2)x^2+(3)x+(1)=0 This equation has two roots Because discriminant is: D = 1 Root1 of the equation is: x1= -0.5 Root2 of the equation is: x2= -1 x1 =    -0.5000 x2 =     -1 D =      1 >> QUAD_01(b, c, a);   % Case 4. The values of a, b, c are mixed up and outputs are not specified Solve: (2)x^2+(3)x+(1)=0 This equation has two roots Because discriminant is: D = 1 Root1 of the equation is: x1= -0.5 Root2 of the equation is: x2= -1 >> a1=1; a2=5; a3=8; >> [X, Y, Dis]=QUAD_01(a1, a2, a3) % Case 5. The output variable names are changed Solve: (1)x^2+(5)x+(8)=0 This equation does not have real value roots! Because discriminant is negative. D = -7 Complex Root1: x1= -2.5+1.3229i Complex Root2: x2= -2.5-1.3229i X =   -2.5000 + 1.3229i Y =   -2.5000 - 1.3229i Dis =     -7

From the five simulations, it is clear that while calling and executing the function files, the names of the input arguments and output variables are not essential. That means users can change the output variables (instead of x1, x2, D) and use different input arguments (other than a, b, c). Furthermore, the function files take the input arguments according to their order (case 2 versus case 3 and case 4). The output variables can be omitted, and the function file will still run, but there will be only one output corresponding to the first output variable specified in the function file’s context.

Most Common Errors with the Function Files

There are a few common mistakes made while working with the function files. They are as follows:

  • Misspelling function names while calling them.

  • Providing the wrong number of input arguments than actually defined in the function file.

  • Calling the wrong number of output variables than actually defined in the function file.

  • Incorrectly using input arguments, such as mismatched size, variable type, etc.

  • Defining the input arguments in the function file and providing their values within the function file context. In other words, defining the input arguments twice without any preconditions of missing arguments and use of alternative (default) values.

Let’s test some of the most common errors that occur when working with the function files in the case of Example 1.

>> t=0:2:720; >> % Error:  Misspelled function name with "M" instead of "m" >> f=Myfunction(t); Cannot find an exact (case-sensitive) match for 'Myfunction' The closest match is: myfunction in C:\ ...\Documents\MATLAB\myfunction.m Did you mean: >> f=myfunction(t);   % MATLAB's automatically detected similar  function name >>  t1 = [0:2:720]; t2= -720:2:0; >> % Error: Two input arguments are inserted instead of one as defined in the function file >> f=myfunction(t1, t2); Error using myfunction Too many input arguments. >>  t2= -720:2:0;   % Input argument name can be altered that is not an ERROR! >> % Error: Two output variables are requested instead of one as defined in the function file >> [f1, f2]=myfunction(t2); Error using myfunction Too many output arguments. >> % Error: Wrong type of input arguments >> t3 =['a', 'b', 'c', 'd', 'f', '-a'  '-b' '-c' '-d' '-f'];  % t3 is a character array and not numerical array >> f=myfunction(t3); Undefined function 'sind' for input arguments of type 'char'. Error in myfunction (line 4) f=3./exp(sind(t))+5./exp(cosd(t));

Let’s analyze the case whereby the input argument is defined within the function file contexts and is called as the input argument while executing the function file. Let’s make some changes to the function file (myfunction.m).

function f=myfunction(t) % HELP: this function file (myfunction.m) computes values of the expression % f(t) = 3./exp(sind(t))+5./exp(cosd(t)) for % given values of t, saves the computed values of f(t) in the workspace, % and plots computed results. % Note that [t] is input argument that has to be in degrees not in radians, % e.g.numerical array, e.g. >> t = -360:720360; % To execute this file: >> t = -720:10:720;  f=myfunction(t); that % assigns output values to a variable f     % and shows the plot. % To execute this file: >> t = 0:1:180;     myfunction(t); that assigns % output values to a variable ans % shows the plot. % To execute this file: >> FF=myfunction(-180:2:360);  that assigns output % values to a variable FF t = 0:720;  % Input variable t is assigned internally f=3./exp(sind(t))+5./exp(cosd(t)); plot(t,f, 'ro-', 'linewidth', 1.5), grid on title('Plot of myfunction.m file')

In this case, the function file takes the input argument values and ignores the input arguments for t when it is called/executed. Here’s an example: >> t =0:1:180; f=myfunction(t);.

The example outputs the computed values of f(t) for t = 0:720 by ignoring our specified input variable t =0:1:180.

Varying Number of Inputs and Outputs

One of the remarkable advantages of the function files over M or MLX-files is that they may have a varying number of input arguments and output variables. This flexibility of the function files can be attained via several MATLAB’s built-in tools, commands, and functions. To vary the number of input arguments, you use varargin, and to vary the output variables, you use varargout. To make these functions more useful with respect to the given problem, there are two other MATLAB built-in tools, commands, and functions, namely, nargin and nargout, which determine how many input arguments and output variables are called while executing the function file. The varying inputs and outputs of the function files can be used in a few different combinations while declaring function input arguments and output variables. Here’s an example:

  1. 1.

    function [Out1, Out2] = function_name(varargin)

  2. 2.

    function varargout = function_name(Input1, Input2, Input3)

  3. 3.

    function varargout = function_name(varargin)

To find out more detailed information on these tools, type the following into the Command window:

>> help varargin >> help varargout >> help narargin >> help narargout >> doc varargin >> doc varargout

Let’s look at two different examples dealing with varying input arguments and output variables.

  1. 1)

    Varying number of inputs and three output variables

  2. 2)

    Varying inputs and varying number of output variables

Example 5

Create a function file (Quad_Var.m) to solve the quadratic equation (ax2 + bx + c = 0) with a varying number of input variables (a, b, c) and with three outputs (x1, x2, D).

function [x1, x2, D]=Quad_Var(varargin) % Quad_Var.m computes roots of the quadratic equation with varying number % of input arguments for a, b, c. Gives three output variables: x1, x2, D. % There are four cases considered: % Case 1. No Input arguments: a =1; b=2; c=3; values are taken as inputs. % Case 2. One Input argument given: a, and b=2, c=3 are taken as inputs. % Case 3. Two Input arguments given: a and b, c=3 is taken as a 3rd input % Case 4. Three Input arguments given: a, b and c. % E.g. % Run: [x1, x2, D] = Quad_Var();        % No Input % Run: [x1, x2, D] = Quad_Var(1);       % One Input: a=1; % Run: [x1, x2, D] = Quad_Var(1, 2);    % Two Inputs: a=1; b=2; % Run: [x1, x2, D] = Quad_Var(1, 2, 3); % Three Inputs: a=1; b=2; c=3; if nargin==0         % Case 1. No input arguments     a=1; b=2; c=3; elseif nargin==1     % Case 2. One input argument only     a=varargin{1}; b=2; c=3; elseif nargin==2     % Case 3. Two input arguments     a=varargin{1}; b=varargin{2}; c=3; else                 % Case 4. Three input arguments     a=varargin{1}; b=varargin{2}; c=varargin{3}; end D=b^2-4*a*c;x1=(-b+sqrt(D))/(2*a); x2=(-b-sqrt(D))/(2*a); end

In the function file Quad_Var.m the MATLAB’s built-in command/tool nargin automatically counts how many inputs are given while calling the function file. The varargin{1} represents the first input argument, varargin{2} represents the second input argument, and likewise varargin{3} represents the third variable. In this order, n varying number of a function file can be created and called.

Let’s test the function file (Quad_Var.m) in four different scenarios:

  • No inputs: The values of a, b, c are taken from the function file context a=1, b=2, c=3.

  • One input: a is given (e.g., a = 1 or any scalar to be assigned to a), and the two values (b, c) are taken from the context of the function file: b =2, c=3.

  • Two input arguments: a, b are given (e.g., a = 1, b = 2 or any scalars to be assigned to a, b), and one input (c) is taken from the context of the function file: c = 3.

  • Three input arguments: a, b, c are given (e.g., a = 1, b = 2, c=3 or any scalars to be assigned to a, b, c).

    >> [x1, x2, D]=Quad_Var         % Case 1. No Input x1 =   -1.0000 + 1.4142i x2 =   -1.0000 - 1.4142i D =     -8 >> [x1, x2, D]=Quad_Var(1)     % Case 2. One Input x1 =   -1.0000 + 1.4142i x2 =   -1.0000 - 1.4142i D =     -8 >> [x1, x2, D]=Quad_Var(1,2)   % Case 3. Two Inputs x1 =   -1.0000 + 1.4142i x2 =   -1.0000 - 1.4142i D =     -8 >> [x1, x2, D]=Quad_Var(1,2, 3) % Case 4. Three Inputs x1 =   -1.0000 + 1.4142i x2 =   -1.0000 - 1.4142i D =     -8

Let’s look at the following example to analyze the varying number of outputs and specific (nonvarying) input arguments (two input arguments).

Example 6

Write a function file to compute the Leibnitz series expansion of arctan(x) to find an approximation of π by using the sum of the Maclaurin series formula for N terms in the following form:

$$ \frac{\pi }{4}\cong {\sum}_{k=0}^N\frac{{\left(-1\right)}^k}{2k+1}={S}_N $$

Write a script that computes the sum (SN) of N terms, which is the approximation of \( \frac{\pi }{4} \). The difference (error) is \( Error=\frac{\pi }{4}-{S}_N \) and Nhalt is the number when the iteration is halted due to the user-specified error tolerance (E_tol) is attained. Use the [for ... end] and [while ... end] loops.

function [varargout] = Leibnitz_VarOut(varargin) % Leibnitz_VarOut.m computes and plot the Leibnitz series expansion of %         arctan(1) to find an approximation of PI. %         Input arguments: %         N (number of terms, e.g. 10000) %         E_tol (Error tolerances, e.g. 0.0001) %         OUTPUT variables are: %         Out1 = Error; %         Out2 = SN (Sum of series); %         Out3 = Nhalt (terms when simulation is halted). if nargin==0     N =1000; E_tol = 0.001; elseif nargin<2     E_tol = 0.001;     N = varargin{1}; else     N = varargin{1}; E_tol=varargin{2}; end SN=0; for ii=0:N     SN = SN+((-1)^ii)/(2*ii+1);     Error=abs(pi/4-SN);     if abs(Error)<=E_tol         Nhalt=ii;         break     else         Nhalt=ii;         continue     end end if nargout == 0        % No Output specified: NO outputs     disp('NO Outputs!') elseif    nargout ==1  % One Output: Error     varargout{1}=Error; elseif nargout ==2     % Two Outputs: Error and Sum of series     varargout{1}=Error; varargout{2}=SN; else      % Three Outputs: Error, Sum of Series, Number of Iterations,     varargout{1}=Error; varargout{2}=SN;varargout{3}= Nhalt; end

If no input arguments are given, then the output will be an error and two input arguments. For example, the number of iterations and error tolerance will be 1000 and 0.001, respectively. If there is one input, then that will be the number of iterations, and the error tolerance will take the value of 0.001.

While executing this function file, if the output variable is not specified, then no outputs will be obtained but only a short note (no outputs!) displayed in the Command window. If one output variable is called (with any variable name), then the achieved last error (Error) value will be the output variable’s value. If two output variables (names) are specified while calling/executing the function file, then the error (Error) and sum of the series (SN) will be output. If three output variables are called, then the Nhalt, SN, and Error values will be obtained. It must be noted that from the specified conditions if the given (N input) number of iterations cannot produce the specified input (E_tol) error tolerance, then Nhalt (the output variable) will be equal to N (the input argument).

[EE, SM]=Leibnitz_VarOut() EE =    1.0000e-03 SM =     0.7844 >> [EE, SM]=Leibnitz_VarOut(10000) EE =    1.0000e-03 SM =     0.7844 >> Leibnitz_VarOut(1e5, 1e-4)    % No output variable specified and thus, No output NO Outputs! >> E = Leibnitz_VarOut(1e5, 1e-4) % One output specified and thus, Error displayed E =    1.0000e-04 >> [ Ee Ss]  = Leibnitz_VarOut(1e5, 1e-4) % Two outputs: Error and Sum of series Ee =    1.0000e-04 Ss =     0.7853 >> [ Ee Ss Nn ]  = Leibnitz_VarOut(1e5, 1e-4) % Three outputs: Error, Sum of series, N Iterations Ee =    1.0000e-04 Ss =     0.7853 Nn =         2499

Let’s look at another example with some computations to demonstrate and analyze the function files with a varying number of input arguments and output variables.

Example 7

Compute the values of this function:

$$ ff(t)=\Big\{{e}^{-2{t}_1}+100{t}_1,\kern1em {t}_1\le -13\kern2em coscos\ \left(100{t}_2\right)-\mathit{\sin}\left(10{t}_2\right)-3\ge {t}_2\ge -13\kern0.5em coscos\ \left(100{t}_3\right)\kern0.5em +{e}^{t_3},\kern0.75em -3\le {t}_3\le 0\ 1,\kern1.5em {t}_4>0 $$

The function f(t) will have four input arguments (t1, t2, t3, t4), whose default set values are t = [t1, t2, t3, t4] ∈ [−20, 6], t1 =  − 20 : 0.001 :  − 13; t2 =  − 12.999 : 0.001 :  − 3; t3 =  − 2.999 : 0.001 : 3; and t4 = 3.001 : 0.001 : 6.

Task 1

Simulate a system within the values of t = [t1, t2, t3, t4], t ∈ [−20, 6] with ∆t = 0.001. Note that this function file may have the following:

  1. 1)

    No input argument and as default values of the function file: t1 =  − 20 : 0.001 :  − 13; t2 =  − 12.999 : 0.001 :  − 3; t3 =  − 2.999 : 0.001 : 3; t4 = 3.001 : 0.001 : 6 will be taken.

  2. 2)

    One input argument that has to represent t as a vector space of data points within [-20, 6].

  3. 3)

    Two or three input arguments, which will be ignored, and the default set values of t1 =  − 20 : 0.001 :  − 13; t2 =  − 12.999 : 0.001 :  − 3; t3 =  − 2.999 : 0.001 : 3; and t4 = 3.001 : 0.001 : 6 will be taken instead.

  4. 4)

    Four input arguments that have to represent t1, t2, t3, t4 in consecutive order.

  5. 5)

    More than four input arguments; then all entries need to be ignored, and some warning messages need to be displayed. Instead of the entries, the default set values of the function file, t1 =  − 20 : 0.001 :  − 13; t2 =  − 12.999 : 0.001 :  − 3; t3 =  − 2.999 : 0.001 : 3; t4 = 3.001 : 0.001 : 6, will be taken.

Task 2

The function file (Ex7Var.m) has to produce any of the following underlined outputs with respect to the call commands of the function file:

  1. 1)

    No outputs and plot of the computed values of f (t)

  2. 2)

    One output: \( {f}_1(t)={e}^{-2{t}_1}+100{t}_1 \)

  3. 3)

    Two outputs: \( {f}_1(t)={e}^{-2{t}_1}+100{t}_1,{f}_2(t)= coscos\ \left(100{t}_2\right)- sinsin\ \left(10{t}_2\right) \)

  4. 4)

    Three outputs: \( {f}_1(t)={e}^{-2{t}_1}+100{t}_1,{f}_2(t)= coscos\ \left(100{t}_2\right)- sinsin\ \left(10{t}_2\right) \),\( {f}_3\kern0.5em (t)=100{t}_3+{e}^{t_3} \)

  5. 5)

    Four outputs: \( {f}_1(t)={e}^{-2{t}_1}+100{t}_1,{f}_2(t)= coscos\ \left(100{t}_2\right)- sinsin\ \left(10{t}_2\right) \),\( {f}_3(t)=100{t}_3+{e}^{t_3},{f}_4(t)=1 \)

  6. 6)

    Five outputs: \( {f}_1(t)={e}^{-2{t}_1}+100{t}_1,{f}_2(t)= coscos\ \left(100{t}_2\right)- sinsin\ \left(10{t}_2\right) \),\( {f}_3(t)=100{t}_3+{e}^{t_3},{f}_4(t)=1,t=t, \)

  7. 7)

    Six outputs: \( {f}_1(t)={e}^{-2{t}_1}+100{t}_1,{f}_2(t)= coscos\ \left(100{t}_2\right)- sinsin\ \left(10{t}_2\right) \),\( {f}_3(t)=100{t}_3+{e}^{t_3},{f}_4(t)=1,t=t,{t}_1 \)

  8. 8)

    Seven outputs: \( {f}_1(t)={e}^{-2{t}_1}+100{t}_1,{f}_2(t)= coscos\ \left(100{t}_2\right)- sinsin\ \left(10{t}_2\right) \),\( {f}_3(t)=100{t}_3+{e}^{t_3},{f}_4(t)=1,t=t,{t}_1,{t}_2 \)

  9. 9)

    Eight outputs: \( {f}_1(t)={e}^{-2{t}_1}+100{t}_1,{f}_2(t)= coscos\ \left(100{t}_2\right)- sinsin\ \left(10{t}_2\right) \),\( {f}_3(t)=100{t}_3+{e}^{t_3},{f}_4(t)=1,t=t,{t}_1,{t}_2,{t}_3 \)

  10. 10)

    Nine outputs: \( {f}_1(t)={e}^{-2{t}_1}+100{t}_1,{f}_2(t)= coscos\ \left(100{t}_2\right)- sinsin\ \left(10{t}_2\right) \),\( {f}_3(t)=100{t}_3+{e}^{t_3},{f}_4(t)=1,t,{t}_1,{t}_2,{t}_3,{t}_4 \)

If more than nine outputs are requested, then the function file will prompt you with a warning message and will note that this function file can produce a maximum of nine output variables.

The final solution script is called Ex7Var.m and has incorporated all the points in tasks 1 and 2 concerning the varying number of input arguments and output variables.

function [f1, f2, f3, f4, t, t1, t2, t3, t4, varargout ] = Ex7Var(varargin) % HELP: Ex7Var.m is a function file to compute a complex function whose % computation function components differ w.r.t the values of t % It may have no, one, two, three, or four input arguments for t % [f1, f2, f3, f4, t] = Ex7Var(t1, t2, t3, t4) % [f1, f2, f3, f4, TT, t1, t2, t3, t4]=Ex7Var(linspace(-20, 6, 10000)); if eq(nargin,0)  % No input argument t1 = -20:.001:-13; t2=-12.999:.001:-3; t3=-2.999:.001:3; t4 = 3.001:1e-3:6; t = [t1,t2, t3, t4]; f1=exp(sin(2*t1))+exp(cos(100*t1)); f2=cos(2*t2)+sin(100*t2); f3=exp(sin(100*t3))+exp(cos(2*t3))+sin(100*t3)+cos(2*t3);     f4=ones(size(t4)); elseif eq(nargin,1)&&min(varargin{1})<=-13&&max(varargin{1})>=6 % One Input     t = varargin{1};     for ii=1:numel(t)         if le(t(ii),-13)             t1(ii)=t(ii);         elseif gt(t(ii),-13) && le(t(ii),-3)             t2(ii)=t(ii);         elseif gt(t(ii),-3) && le(t(ii),3)             t3(ii)=t(ii);         else             t4(ii)=t(ii);         end     end                       f1=exp(sin(2*t1))+exp(cos(100*t1));   t2=t2(find(t2~=0)); f2=cos(2*t2)+sin(100*t2);   t3=t3(find(t3~=0));f3=exp(sin(100*t3))+exp(cos(t3))+sin(100*t3)+cos(2*t3);   t4=t4(find(t4~=0)); f4=ones(size(t4)); elseif gt(nargin,1) && lt(nargin,4) % Two or Three Inputs     warndlg('t series need to be in four separate ranges or one united !!!')     warndlg('Your entries are ignored and example data taken instead!!!')     t1=-20:.001:-13; t2=-13.001:.001:-3; t3=-3.001:.001:3; t4=3.001:1e-3:6;     t = [t1,t2, t3, t4];     f1=exp(sin(2*t1))+exp(cos(100*t1)); f2=cos(2*t2)+sin(100*t2);     f3=exp(sin(100*t3))+exp(cos(2*t3))+sin(100*t3)+cos(2*t3);   f4=ones(size(t4)); elseif eq(nargin, 4)               % Four Inputs     t1 = varargin{1}; t2=varargin{2}; t3=varargin{3}; t4 = varargin{4};     t = [t1,t2, t3, t4];     f1=exp(sin(2*t1))+exp(cos(100*t1)); f2=cos(2*t2)+sin(100*t2);     f3=exp(sin(100*t3))+exp(cos(2*t3))+sin(100*t3)+cos(2*t3); f4=ones(size(t4)); else                               % More than Four Inputs warndlg('Check your entries: input arguments for [t] or [t1, t2, t3, t4]')     warndlg('Your entries are ignored and default data taken instead!!!')     t1=-20:.001:-13;t2=-12.999:.001:-3; t3=-2.999:.001:3; t4 = 3.001:1e-3:6;     t = [t1,t2, t3, t4];     f1=exp(sin(2*t1))+exp(cos(100*t1)); f2=cos(2*t2)+sin(100*t2);     f3=exp(sin(100*t3))+exp(cos(2*t3))+sin(100*t3)+cos(2*t3);    f4=ones(size(t4)); end plot(t1, f1, 'r', t2, f2, 'b', t3, f3, 'm',t4, f4, 'go--'), grid on; shg; legend('toggle') % Set number of output variables is verified MIN_outs = 0; MAX_outs=9; if nargout>MAX_outs fprintf('Asked %3g outputs that are more than set outputs!!! \n', nargout); warndlg('This fucntion file is assigned to have max. of 9 outputs!!!') fprintf('Asked %3g outputs are beyond the set outputs !!! \n', nargout); end % NARGOUTCHK; Checks and prompts error if the number of outputs requested % by the user is beyond 9! % nargoutchk(MIN_outs, MAX_outs) % Can be also employed end

It should be noted that in the Ex7Var.m function file, the nargin function will check how many input arguments are specified while calling this function file for task 1. The function’s input arguments are taken for simulations depending on the number of the input arguments verified within the [if... elseif... elsefif ... elseif ... else ... end] conditional operators, addressing all points in task 1 for input arguments.

Moreover, the [for ... end] loop operator with another internal [if ...elseif ... elseif...else...end] conditional operator set after a first ([elseif ...]) splits up the given one input argument (t) values for four separate sets of values for t1, t2, t3, t4 according to the given exercise statements.

The logical indexing operations of find( ) with ~= 0 define which elements (taken from t within [for ... end] loop and [if ...elseif ... elseif...else...end] operations) of t2, t3, t4 are to be taken for simulations to skip overlapping points. When the user enters two or three input arguments, nargin and [elseif ...] verify the entry. Two warning message dialogs will pop up informing the user that all entries are ignored and the default values are taken instead.

In the case of four input arguments, all input arguments are considered in the order of t1, t2, t3, t4, and simulations are performed. If the number of input arguments exceeds four, then again two warning message dialogs will pop up informing the user that all entries are ignored and the default values are taken instead. The plot( ) command plots all of the simulation results. This completes all verifications.

The specified MIN_outs = 0; MAX_outs=9; along with nargout verify the number of requested outputs. At this area of the script, the nargoutchk function can be also employed to detect the wrong number of requested output variables. If the requested number of outputs is more than nine, the warning message is displayed in the Command window. A plot figure is displayed, a warning dialog is displayed, and no output variables are obtained. The conditional statements [if ... elseif... ... end] with nargout determines which output corresponds to which simulation output.

Let’s test the script (Ex8Var.m) for a different number of input arguments and output variables.

  1. 1)

    No input and no output

    >> Ex7Var(); No outputs!

There will be no computation results except for the plot figure shown in Figure 2-8.

Figure 2-8
A graph plots sinusoidal curves for data 1, 2, and 3. The values for data 3 are the highest. Data 4 has a line parallel to the horizontal axis at 1.

Plot of the simulation results \( f(t)=\Big\{{e}^{-2{t}_1}+100{t}_1,\kern1em {t}_1\le -13\kern2em coscos\ \left(100{t}_2\right)-\mathit{\sin}\left(10{t}_2\right)-3\ge {t}_2\ge -13\kern0.5em coscos\ \left(100{t}_3\right)\kern0.5em +{e}^{t_3},\kern0.75em -3\le {t}_3\le 0\ 1,\kern1.5em {t}_4>0 \)

  1. 2)

    One input t is given, and four outputs are requested:

    >> t=linspace(-20, 6, 1000); >> [f1, f2, f3, f4]=Ex7Var(t); >> whos Name      Size              Bytes  Class     Attributes  f1        1x269              2152  double  f2        1x385              3080  double  f3        1x230              1840  double  f4        1x116               928  double  t         1x1000             8000  double

Four outputs (f1, f2, f3, f4) are saved in the workspace and the plot figure (shown in Figure 2-8).

  1. 3)

    No input and nine output variables are requested:

    >> clearvars; >> clearvars; [f1, f2, f3, f4, t_all, t1, t2, t3, t4]=Ex7Var(); >> whos   Name       Size                Bytes  Class     Attributes   f1         1x7001              56008  double   f2         1x10000             80000  double   f3         1x6000              48000  double   f4         1x3000              24000  double   t1         1x7001              56008  double   t2         1x10000             80000  double   t3         1x6000              48000  double   t4         1x3000              24000  double   t_all      1x26001            208008  double

Nine outputs (f1, f2, f3, f4, t1, t2, t3, t4, t_all) are obtained in the workspace.

  1. 4)

    Three input arguments and no output variables are requested:

    >> clearvars; t=-20:.005:6; t3=-2.999:.002:3; t4 = 3.001:1e-2:6; >> Ex7Var(t, t3, t4); No outputs! >> whos   Name      Size              Bytes  Class     Attributes   t         1x5201            41608  double   t3        1x3000            24000  double   t4        1x300              2400  double

There are no outputs in the workspace from the simulations except for entries (input arguments, t, t3, t4), and there is a plot figure in Figure 2-8. In addition, the following two warning dialog boxes are displayed, stating the mismatch of the entries with the necessary t series, and the input entries are ignored:

A screenshot of a dialog box titled warning dialog. The warning text reads t series need to be in four separate ranges or one united 3 exclamation mark.
A screenshot of a dialog box for warning dialog. The warning text reads your entries are ignored and example data taken instead 3 exclamation marks.
  1. 5)

    Three input arguments and three output variables are requested:

    >>clearvars; t_all=-20:.001:6; In2=-2.999:.001:3; In3 = 3.001:1e-3:6; >> [Out1, Out2, Out3]=Ex7Var(t_all, In2, In3); >> whos   Name      Size                Bytes  Class     Attributes   Out1      1x7001              56008  double   Out2      1x10000             80000  double   Out3      1x6000              48000  double   t_all         1x26001            208008  double   In2        1x6000              48000  double   In3        1x3000              24000  double

Three outputs (Out1, Out2, and Out3 representing f1, f2, and f3, respectively) from the simulations and entries (input arguments: t_all, In2, In3) are obtained in the workspace. There is a plot figure as well (Figure 2-8). In addition, there are two warning dialog boxes displayed as shown in the previous case.

Note

While calling/executing the function files, output variable names and input argument names can be altered. That would not cause any errors. This is one of the useful attributes of the function files over M/MLX-files.

  1. 6)

    Four input arguments representing t1, t2, t3, t4 and nine output variables representing f1, f2, f3, f4, t_all, t1, t2, t3, t4 are requested:

    >> clearvars t1 = -20:.0025:-13; t2=-12.999:.005:-3; t3=-2.999:.002:3; t4 = 3.001:5e-3:6; >> [f1, f2, f3, f4, T_all, time1, time2, time3, time4]=Ex8Var(t1, t2, t3, t4); >> whos   Name       Size              Bytes  Class     Attributes   T_all      1x8401            67208  double   f1         1x2801            22408  double   f2         1x2000            16000  double   f3         1x3000            24000  double   f4         1x600              4800  double   t1         1x2801            22408  double   t2         1x2000            16000  double   t3         1x3000            24000  double   t4         1x600              4800  double   time1      1x2801            22408  double   time2      1x2000            16000  double   time3      1x3000            24000  double   time4      1x600              4800  double

All requested output variables are obtained in the workspace along with the plot figure (Figure 2-8). Moreover, it should be noted that the input entries (arguments) t1, t2, t3, and t4 match with the output variables time1, time2, time3, and time4, respectively.

  1. 7)

    Nine output variables representing f1, f2, f3, f4, t_all, t1, t2, t3, t4 are requested without any input arguments:

    >> clearvars >> [f1, f2, f3, f4, T_all, time1, time2, time3, time4]=Ex7Var(); >> whos   Name       Size                Bytes  Class     Attributes   T_all      1x26001            208008  double   f1         1x7001              56008  double   f2         1x10000             80000  double   f3         1x6000              48000  double   f4         1x3000              24000  double   time1      1x7001              56008  double   time2      1x10000             80000  double   time3      1x6000              48000  double   time4      1x3000              24000  double

With no input arguments and requesting only nine output variables, the function file produces nine output variables with the assigned output variable names in the workspace by using the default set values for t1, t2, t3, t4 and the plot figure (Figure 2-8).

  1. 8)

    With one input for t and 10 outputs:

    >> clearvars >> tall=-20:.001:6; >> [f1, f2, f3, f4, T_all, time1, time2, time3, time4, T_all]=Ex7Var(tall); Asked  10 outputs are beyond the set outputs !!! One or more output arguments not assigned during call to "varargout". >> whos   Name      Size                Bytes  Class     Attributes   tall      1x26001            208008  double

A screenshot of a dialog box titled warning dialog. The warning text reads this function is assigned to have a maximum of 9 outputs three exclamation marks.

The 10th output variable is beyond the number of assigned output variables. Therefore, the function file does not produce any output variables in the workspace except for two warning messages, warning dialogs, and the plot figure (Figure 2-8).

There are many other possible scenarios to test this function file for robustness. By default the robustness of this function file is considerably high within the predefined conditions of the exercise for input arguments in particular. But there are a few other cases in which the outputs of this function file may not be accurate due to inaccurately chosen entries for t, or t1, t2, t3, t4 . For example, one input for t might contain just two elements ([-20, 6]) of a row or column vector. Or similarly, the entries for t1, t2, t3, t4 might also be [-20, -13], [-12.999, -3], [-2.999, 3], [3.001, 6]. To improve the robustness of this function file, you can use MATLAB’s built-in tool/operator nargchk to verify the allowable number of input arguments along with nargin. Likewise, another built-in tool/operator nargoutchk can be used to verify the number of defined output variables along with nargout.

Nested and Subfunctions of Function Files

The function files may contain more one, two, three, or more nested (subfunctions) functions to perform specific computations and analyses. The general syntax of such function files is as follows:

function [Output1, Output2, Output3, ...] = MAIN(In1, In2, In3, ...) % MAIN.m contains several nested sub-functions Output1 = Nest1; Output2 = Nest2; Output3 = Nest3; ... function Out1Nest1() Out1 = [do sth] end function Out2=Nest2(In2) Out2 = [do sth] end function Out3=Nest3(In3) Out3 = [do sth] end Code

Let’s look at several examples how to employ nested (subfunctions) functions in a function file.

Example 8

This example generates three different square matrices (of Pascal, Cauchy, Krylov) within three nested functions with respect to the main function’s input arguments (only integers). Note that input arguments (integers) define the size of the output magic matrices.

Here is the solution script; it is a function file called Ex8_MAIN:

function [Output1,Output2, Output3] = Ex8_MAIN(In1,In2, In3) % Ex8_MAIN.m generates three square matrices within three nested functions %   Input arguments: In1, In2, In3 are integers defining the size of the %   output matrices. %   Nest1 generates the square matrix of Pascal %   Nest2 generates the square matrix of Cauchy %   Nest3 generates the square matrix of Krylov disp(['This is ' num2str(In1)  '-by-' num2str(In1) ' Pascal matrix']) Output1 = Nest1; disp(Output1) disp(['This is ' num2str(In2)  '-by-' num2str(In2) ' Cauchy matrix']) Output2 = Nest2; disp(Output2) disp(['This is ' num2str(In3)  '-by-' num2str(In3) ' Krylov matrix']) Output3 = Nest3; disp(Output3)     function Out1=Nest1() %   Nest1 generates the square matrix of Pascal         Out1 = pascal(In1);     end     function Out2=Nest2() %   Nest2 generates the square matrix of Cauchy         Out2 = gallery('cauchy',In2);     end     function Out3=Nest3() %   Nest3 generates the square matrix of Krylov         Out3 = gallery('krylov',In3);     end end

Now, let’s test the function file with three nested functions:

>> Input1 = 2; Input2=3; Input3=4; >> [Output1,Output2, Output3] = Ex8_MAIN(Input1,Input2, Input3); This is 2-by-2 Pascal matrix      1     1      1     2 This is 3-by-3 Cauchy matrix     0.5000    0.3333    0.2500     0.3333    0.2500    0.2000     0.2500    0.2000    0.1667 This is 4-by-4 Krylov matrix     1.0000    0.6731    3.8494   -2.7613     1.0000    1.7986    2.3591    4.8361     1.0000   -0.8049    1.0833   -0.5926     1.0000    1.7760   -1.1635    1.2842 >> whos   Name         Size            Bytes  Class     Attributes   Input1       1x1                 8  double   Input2       1x1                 8  double   Input3       1x1                 8  double   Output1      2x2                32  double   Output2      3x3                72  double   Output3      4x4               128  double

Function Files Within M-Files

In recent versions of MATLAB, the function files (including nested and subfunctions) can be employed within M-files. This makes the computation process more efficient and saves memory space in the workspace. Let’s take a look at the following example.

Example 9

Given: y(x, t) = y0 sin (kx − ωt) that is the solution of the wave equation. Here, \( k=\frac{2\pi }{\lambda } \) is the wave number, ω = 2πf is the angular frequency, and λ is the wavelength.

Write an M-file with two nested functions to compute the values of y(x, t) with four input arguments of k, ω,x, t.

Given \( {y}_0=\frac{1}{2};\lambda =495\ast {10}^{-9};k=\frac{2\pi }{\lambda };f=5000;\omega =2\pi f;x=\left[0,1\right],t=\left[0,5\right]; \) N = 106 (number of data points for x and t).

The solution script is called Ex9_wFUN.m that has two embedded functions follows:

y0=1/2;                   % Magnitude of the wave lambda=495e-9;            % Visible light wave length k=2*pi/lambda;            % Wave number f=5000;                   % Frequency omega=2*pi*f;             % Angular frequency x=[0, 1e-5];              % Length t=[0, 1e-3];              % Time length N=1e5;                    % Number of data points to be computed & simulated xs=linspace(x(1), x(2), N);    % Wave Length series time=linspace(t(1), t(2), N);  % Time series y1 = F1(y0, k, xs, omega, time); y2 = F2(y0, k, time, omega, xs); % NB: it is vital the order of the varaibales: xs vs. time && V5 vs. V3 plot(xs, y1, 'bo', xs, y2, 'rx-'), grid on, hold on title('Nested Function files within an M-file') ORG0 = y0*sin(k*xs-omega*time); plot(xs, ORG0, 'k', 'linewidth', 2) legend('Fun1','Fun2','Original'), shg function out1 = F1(var1, var2, var3, var4, var5) % M-file nested function 1 called: F1 out1=var1*sin(var2*var3-var4*var5); end function out2 = F2(V1, V2, V3, V4, V5) % M-file nested function 2 called: F2 % NB: it is vital the order of the variables: xs vs. time && V5 vs. V3 out2=V1*sin(V2*V5-V4*V3); end

This is an M-file that can be executed by clicking the Run button in the menu panel or can be called from another M-file or from the Command window. After executing the file, you would get the following output:

>> clearvars >> Ex9_wFUN >> whos   Name        Size                 Bytes  Class     Attributes   N           1x1                      8  double   ORG0        1x100000            800000  double   f           1x1                      8  double   k           1x1                      8  double   lambda      1x1                      8  double   omega       1x1                      8  double   t           1x2                     16  double   time        1x100000            800000  double   x           1x2                     16  double   xs          1x100000            800000  double   y0          1x1                      8  double   y1          1x100000            800000  double   y2          1x100000            800000  double

In addition, the plot in Figure 2-9 is created.

Figure 2-9
A line graph is titled nested function files within an M-file. The graph plots overlapping sinusoidal curves for fun 1, fun 2, and original.

Comparing the simulations obtained from the nested functions within the M-file

The simulation results show that the M-file with embedded functions works like any other M-file. Like with the function files, the order of the input arguments is vital for the embedded functions within M-files. If the order is mixed up, then the outputs will be incorrect because one variable’s values will be used for another.

Summary of Scripts and Function Files

Warning and error messages included in M-files and function files are of great help not only to users but also to developers. Thus, when you are writing scripts (programs), it is important to add as warning and error messages along with additional hints (as comments).

Consider these essential hints on how to write robust and efficient M-files and function files:

  • Do as much checking (of input and output arguments, e.g., size, data type) as possible before executing a whole script to avoid the heavy burden of time-consuming calculations that may result in incorrect outputs.

  • Always start with most general checks (obvious ones) and then move to more complicated and complex ones. Add warning and error messages wherever necessary or appropriate. For example, add a unique text for display (e.g., disp('This is ...')) during the debugging process when you have varying numbers of input arguments and output variables. These messages not only help developers to spot errors but also go through all the anticipated scenarios in the code/script.

  • Explain how to correct errors when they occur using a warning message, e.g., warning('Do something about this and that ...', A, B, C) and an error message, e.g., error('There is an error on this and that ...', Num(1), Den(3), u(1)).

  • Add warning message identifiers so users can turn warnings on and off.

  • Add numerical examples to test your script with known correct solutions.

  • Use the M-file profiler to check the efficiency of your created M-files. To use the profiler, type >> profile on; My_function; profile viewer in the Command window.

Inline Functions

The MATLAB command inline lets users develop one or more analytical expressions with one or more input variables and assign that expression to a variable. A general syntax of creating an inline function expression is: f=inline('[expression1; expression2, ...]','arg1','arg2','arg3', ...);

In this command syntax, expression1, expression2, and so on, are inline functions and arg1, arg2, arg3, and so on, are input variables.

Note

An inline function is not recommended; instead, a function file is recommended.

Example 1

\( f(t)=\frac{\mathit{\sin}(2t)}{e^{2t}} \) can be expressed via a straightforward inline function without any argument definition, since there is one variable that is identified automatically.

>> f = inline('sin(2*t)/exp(2*t)');

Example 2

The inline function of f(t, θ) = [e−2; sin(2t)] should contain two input arguments, namely, t, θ. Therefore, the given function expressions can be expressed via the following inline function:

>> F = inline('[exp(2*t.*theta); sin(2*t)]', 't', 'theta');

That can be tested with predefined arguments, t and theta.

>> t=0:pi/20:pi; theta=linspace(0,1,length(t));

You can get the calculation results from the inline function F simply by recalling it with predefined input arguments.

>> fcalc=F(t, theta);

In addition, it is possible to perform computations and plot computed data from the inline function F simultaneously.

>> plot(t, log(F(t, theta)), 'linewidth', 1.5);

Example 3

Given: a second-order differential equation \( \ddot{y}+\dot{y}+3\ y={t}^2 \)that can be expressed by two first-order differential equations.

$$ \Big\{{\dot{y}}_1={y}_2\ {\dot{y}}_2={t}^2-\left({y}_2+3{y}_1\right) $$

These two first-order differential equations can be defined by the following inline function:

f =inline('[y(2); t^2-(y(2)+3*y(1))]', 't', 'y');

Based on the previously shown examples, you can see that it is easy and straightforward to use the inline function tool not only in the Command window but also within scripts to solve various computation problems.

Note

The inline command will be removed in future releases of MATLAB, and therefore, it is recommended that you use anonymous functions instead.

Anonymous Functions with Handles

An anonymous function is a function that is not stored in a program file. It is associated with a variable and is called with a function handle (@). In general, the function handles accept input variables and return output variables similar to function files (as demonstrated previously). One major difference between a function file and an anonymous function expression is that an anonymous function with a handle (@) contains a single executable statement. The general syntax of expression anonymous functions with handles is as follows:

Fun_handle=@(arg1, arg2, arg3, ...)([expression1; expression2;...])

Example 1

$$ f(t)=\frac{\mathit{\sin}(2t)}{e^{2t}} $$

The given function f(t) can be expressed via a function handle with the following command:

>> f_handle = @(t)(sin(2*t)./exp(2*t)); >> t=linspace(0,2*pi, 100); >> f=f_handle(t); plot(t, f, 'o-')

It is also feasible to use function handles within loop iterations of scripts, for instance, Fun_handle.m.

% Fun_handle.m f_handle = @(t)(sin(2*t)./exp(2*t)); t=linspace(0,2*pi, 100); for ii=1:length(t)     f(ii)=f_handle(t(ii)); end plot(t, f, 'o-') title('plot: f(t)=(sin(2*t)./exp(2*t)')

Example 2

Given f(t, θ) = [e−2; sin (2t) ].

The given function f(t, θ) can be expressed via one function handle.

>> F_handle = @(t, theta)([exp(2*t.*theta); sin(2*t)]);

Let’s specify data values for input arguments of t and theta.

>> t=0:pi/20:pi; theta=linspace(0,1,length(t));

To obtain computation results from the function handle F_handle, the function handle has to be recalled with input arguments of t and theta.

>> Fvalues=F_handle(t, theta);

Example 3

Given: \( \ddot{y}+\dot{y}+3\ y={t}^2 \)

It can be expressed by two first-order differential equations in a state-space form.

$$ \Big\{{\dot{y}}_1={y}_2\ {\dot{y}}_2={t}^2-\left({y}_2+3{y}_1\right) $$

The previously derived system of two first-order differential equations can be defined via the following function handle (@):

f =@(t, y)([y(2); t^2-(y(2)+3*y(1))]);

The function handle (@) tool of an anonymous function can be also implemented like an inline function within scripts to solve many different kinds of problems including differential equations.

Up to this point, in a few examples, we have demonstrated how to employ function files, inline functions, and anonymous function tools. There are some advantages and disadvantages of employing anonymous functions defined with handles (@) and inline functions in comparison to function files. Anonymous functions are easy to implement and design, and there is a very small chance of getting confused with the function name and input arguments. On the other hand, one of the main advantages of function files over function handles and inline functions is that they are more efficient and flexible in terms of computation time. This is important when numerical simulation space is large. Moreover, function files can be employed within Simulink models.

Summary

In this chapter, we covered all the basic programming essentials, including different operators and symbols used in programming and how to employ them efficiently. Moreover, we highlighted the most frequently occurring potential programming errors and pitfalls and how to avoid them.

In summary, to speed up simulation/computation processes, there are a few procedures to follow while coding. When you are dealing with large data sets, you may face memory problems. To prevent memory problems or errors in MATLAB, or to just improve computation efficiency, the following tips are recommended:

  • Avoid large temporary variables, break variables into smaller components, and clear variables (using clearvars) when they are no longer needed.

  • Use lower-precision data types, if possible, and whenever there is no need for higher precision.

  • Pre-allocate memory for arrays of fixed size to reduce defragmentation by using standard matrices such as zeros() or ones().

  • Use the function pack() to defragment memory.

  • Consider writing data to a disk periodically.

  • Increase the size of a swap file. This can be done via My Computer ➤ properties ➤ Advanced - Performance Settings.. Note that it is recommended to set the swap file size to twice the size of your computer’s RAM.

Here are some other techniques to speed up the simulation processes:

  • Functions (function files) are faster than scripts.

  • Load and save are faster than file I/O functions when you need to import or export data sets.

  • Avoid large background processes.

  • Replace argument checking with try-catch.

  • Use switch-case over if-elseif-else.

  • Use sparse arrays for sparse data.

Exercises for Self-Testing

Exercise 1

Write an M-file using the [while, end] loop control statement to compute the values of the cosine function g(θ) =  cos (θ) for θ = 0...π with 2,000 incremental steps in this range and stop computation when the value of the function g(θ) ≈ 0.99999. Also, display how many steps it takes to get through the computation process and plot your simulation results. Also, display the end value of 0.99999 in the same plot.

Exercise 2

Compute the area of a circle, square, and rectangle with regard to these user entries:

W = input('Width of a rectangle:        '); L = input('Length of a rectangle:       '); R = input('Radius of a circle:          '); S = input('Side length of a square:     ');

There are several scenarios to consider in your script: (1) if a user enters two dimensions for the width (W) and length (L) of a rectangle, your code has to compute the area of a rectangle and display it with comments; (2) if a user enters two dimensions, such as radius (R) and side (S) of a square, it has to compute the area of a circle and square, respectively, and display it with comments; (3) if a user enters all the required entries, it has to compute three areas and display with adequate comments; (4) if a user enters not all entries or misses any of the required entries (W, L, R, S), your code has to display "You need to ENTER all dimensions!". The input(), isempty(), exist(), length(), numel(), size(), and fprintf() commands can be employed.

Exercise 3

Write a script to display student grades based on their earned points. Student grades have to be defined according to the following scales:

            F =  0...65;             D =  66 ... 70;             C =  71 ... 81;             B =  82 ... 87;             A  =  88 ... 100;

Use input(), disp(), fprintf(), [if, elseif, else ... end].

Test your script with these example points: [70, 82, 35, 90, 99, 56, 81, 89, 66, 87, 88, 83, 71, 69, 55].

Exercise 4

These exercises cover the [while, end] and [for, end] loop control operators:

  1. 1.

    Compute the series \( \frac{\pi^2}{8}=1+\frac{1}{3^2}+\frac{1}{5^2}+\frac{1}{7^2}+\dots ={\sum}_{n=0}^{\infty}\frac{1}{{\left(2n+1\right)}^2} \) using the [while, end] and [for, end] loop control statements. Take n = 101 and plot error values over iterations.

  2. 2.

    Compute the sum of these series: 12, 22, 32, ...n2. Take n = 500 and compute the total sum \( {\sum}_{n=1}^{500}{n}^2 \) using the [while, end] and [for, end] loop control statements. Plot the sum as a function of n.

  3. 3.

    Compute the sum of these series: 1 ∗ 2 + 2 ∗ 3 + 3 ∗ 4 + 4 ∗ 5 + .... This can be rewritten as a sum \( {\sum}_{k=1}^Nk\left(k+1\right). \) To compute the total sum, use the [while, end] and [for, end] loop control statements. Plot the sum as a function of k.

  4. 4.

    Compute these series (discovered by Euler in 1735): \( \frac{\pi^2}{6}=1+\frac{1}{2^2}+\frac{1}{3^2}+\frac{1}{4^2}+\dots ={\sum}_{n=1}^{\infty}\frac{1}{n^2} \) using the [while, end] and [for, end] loop control statements. Take n = 1...99 and plot error values over iterations. Run the exhaustive computation and halt the computation process when the error is smaller than 10−13.

  5. 5.

    Compute the total sum of this series of odd numbers, namely, 1, 3, 5, 7, ..., that can be written in the form of this sequence 2n + 1. Take N = 111111 and compute the total sum \( {\sum}_{n=0}^N\left(2n+1\right) \)using the [while, end] and [for, end] loop control statements. Halt the iteration process when the sum is larger than 30869136. Display the final number as an integer. Plot the summing iteration process.

Exercise 5

Write a script file with the conditional statements [if, elseif, elseif, else, end] and the function handle (@) to compute the values of the function:

$$ g\left(a,b,t\right)=\Big\{{e}^{- at}+ bt,\kern0.75em t\le -13\kern1.25em \mathit{\cos}\ (at)- si(bt),\kern0.75em -3\ge t\ge -13\kern0.75em \mathit{\cos}\kern0.5em at+{e}^{bt},\kern0.75em -3\le t\le 0\ 1,\kern1em t>0 $$
$$ a=3,\kern0.5em b=2. $$

Exercise 6

Here are some exercises for the [while, end] and [for, end] loop control operators:

  1. 1.

    Compute this series: f (x)= \( {\sum}_{n=1}^{\infty}\frac{b_n\mathit{\sin}\left(\left(2n-1\right)\pi x\right)}{2L} \) using the [while ... end] and [for ... end] loop control statements. Take n = 11, bn = [−5...5], x = [0...L], and L = 10. For x take a step size of \( \Delta x=\frac{L}{100}. \) Plot all computation results.

  2. 2.

    Compute f (t) = cos cos (20t) −  sin (10t) for t ∈ [−π,  π] with ∆t = π/50 using the [while ... end] and [for ... end] loops.

Exercise 7

These exercises cover the [while ... end] and [for ... end] loop operators:

  1. 1.

    Compute the total sum of these series: \( \frac{3}{4}+\frac{4}{5}+\frac{5}{6}+\frac{6}{7}\dots ={\sum}_{m=3}^{55}\frac{m}{m+1} \). Compute the total sum using the [while, end] and [for, end] loop control statements. Plot the sum as a function of m.

  2. 2.

    Compute the total sum of these series: \( 10+30+90+270+810+2430+\dots ={\sum}_{m=0}^{65}\left(10\ast {3}^k\right) \). Compute the total sum using the [while, end] and [for, end] loop control statements, and halt the computation process when the sum is larger than 18446744073709551615. Display the final sum number as an integer. Plot the sum as a function of k.

  3. 3.

    Compute the sequence 4, 1, 0.5, 0.25, ... until it is smaller than 0.000005 by using the [while, end] and [for, end] loop control statements. Note that the sequence can be formulated as 4 ∗ (0.5)n − 1. Find n that makes the sequence smaller than 0.000005.

  4. 4.

    Compute the total sum of the series \( \frac{1}{2}+\frac{1}{4}+\frac{1}{8}+\frac{1}{16}+\dots \) until it is equal to or larger than 0.999 999 999. Note that the sum of this series can be expressed with \( {\sum}_{k=0}^n\frac{1}{2}{\left(\frac{1}{2}\right)}^k. \)

  5. 5.

    Compute the following total sum of \( {\sum}_{n=0}^m\frac{{\left(-1\right)}^n{x}^{2n+1}\kern0.5em }{\left(2n+1\right)!} \) for m = 202 and x = 2.5 by using the [while, end] and [for, end] loop control statements.

  6. 6.

    Compute the following total sum of \( {\sum}_{n=1}^m\frac{{\left(-1\right)}^{n+1}{\left(x-1\right)}^n\kern0.5em }{n\ } \) for m = 1001 and x = 2 by using the [while, end] and [for, end] loop control statements.

Exercise 8

Fix two errors in the following given script:

%% Find out if the entry is a Scalar or NOT. % Prepare your entry data that MUST be in array % or matrix format of any size: 1-by-1, 2-by-2, 2-by-3, etc, etc! % Your entry can be also any standard array generating functions! ABC=input('Enter ANY numerical entry of any size surrounded with square brackets [  ]:   '); if isnumeric(ABC) && isscalar(ABC)     fprintf('This is a scalar: %20g \n', ABC); else     format short     fprintf('Your entry is not scalar, but an array \n', ABC);     fprintf(ABC); end

  1. 1.

    After fixing the errors, the code has to produce the following outputs in the Command window with the user entry of [1, 2; 3,-1]:

    Enter ANY numerical entry of any size within [  ]:   [1, 2; 3,-1] Your entry is not scalar, but an array      1     2      3    -1

  2. 2.

    The code has to produce the following outputs in the Command window with the user entry of ['ab' 'bc'; 'cd' 'ef']:

    Enter ANY numerical entry of any size within [  ]:   ['ab' 'bc'; 'cd'  'ef'] Your entry is not scalar, but an array abbc cdef

  3. 3.

    The code has to produce the following outputs in the Command window with the user entry of 13.12:

    Enter ANY numerical entry of any size within [  ]:   13.12 This is a scalar:                13.12

Exercise 9

Fix the three errors in the following script:

%% Find out whether the array is square and if it is, show its size. % Prepare your entry data that MUST be in array % or matrix format of any size: 1-by-1, 2-by-2, 2-by-3, etc, etc! % Your entry can be also any standard array generating functions!!! ABC=input('Enter ANY numerical entry of any size within [  ]:   '); [Rows, Cols]=size(ABC); if isnumeric(ABC) && Rows==Rows     fprintf('This is a square ARRAY! ');     fprintf('Your entry is of %5g -by- %5g  square ARRAY \n', Cols, Rows); else     format short     fprintf('Your entry is NOT a square array \n')     fprintf('BUT an ARRAY of size %5g - by - %5g \n', Cols, Cols); end

After fixing the errors, the code has to produce the following outputs in the Command window, given these entries:

  1. 1.

    Entry: [magic(5)]

    Enter ANY numerical entry of any size within [  ]:   [magic(5)] This is a square ARRAY! Your entry is of     5 -by-     5  square ARRAY

  2. 2.

    Entry: [rand(3,5)]

    Enter ANY numerical entry of any size within [  ]:   [rand(3,5)] Your entry is NOT a square array BUT an ARRAY of size     3 - by -     5

Exercise 10

Fix the two errors in the following script:

%% Find out: the user entry is scalar or not. If it is, display it. % otherwise, show the variable type. ABC=input('Enter ANY numerical entry of any size within [  ]:   '); if isnumeric(ABC)     fprintf('This is a Scalar! \n');     fprintf('Your entry is a scalar:  %5g  \n', ABC); else     class(ABC, 1) end

After fixing the two errors, the following outputs are obtained with respective inputs.

For entry 1:

Enter ANY numerical entry of any size within [  ]:   123 This is a Scalar! Your entry is a scalar:    123

For entry 2:

Enter ANY numerical entry of any size within [  ]:   '1001011' ans =     'char'

For entry 3:

Enter ANY numerical entry of any size within [  ]:   [1 3 -2] ans =     'double'

Exercise 11

Fix two errors in the following script:

%% Find out: the array is real and square. If it is, display it; % otherwise, show its size and type. % NB: size(), display(), class() can be used. % Prepare your entry data that MUST be in array % or matrix format of any size: 1-by-1, 2-by-2, 2-by-3, etc. % Your entry can be also any standard array generating functions! ABC=input('Enter ANY numerical entry of any size within [  ]:   '); [Rs, Cs]=size(ABC); if ischar(ABC) && Rs==Cs     fprintf('This is a square array! \n');     disp(ABC); elseif format short fprintf('This is not a square array & its size: %5g-by-%5g \n', Rs, Cs); disp(num2str(ABC)); end

After fixing the two errors, the following outputs should be obtained with respective inputs.

Entry 1:

Enter ANY numerical entry of any size within [  ]:   magic(3) This is a square array!      8     1     6      3     5     7      4     9     2

Entry 2:

Prepare your entry data that MUST be in array or matrix format of any size 1-by-1, 2-by-2, 2-by-3, etc., etc.! with real value elements Your entry can be also any standard array generating functions!!! Enter ANY numerical entry of any size within [  ]:   [1, 2/0; 0/0, 1] This is a square array!       1   Inf    NaN     1

Entry 3:

Your entry can be also any standard array generating functions!!! Enter ANY numerical entry of any size within [  ]:   [1, 2/0; 0/0, 1; 1, 0] This is not a square array and its size:     3 - by -     2   1  Inf NaN    1 1   0

Exercise 12

Fix the five errors in the following script:

%% Q7. Computing area of a circle, square and rectangle w.r.t the user entries: W = input('Width of a rectangle:          ', 's'); L = input('Length of a rectangle:         ', 's'); R = input('Radius of a circle:            ', 's'); S = input('Side length of a square:       ', 's'); if isempty(R) && isempty(S)     A1=W*L;     fprintf('Area of a rectangle:  A1 =  %5g \n', A1); elseif isempty(W) && isempty(L) && exist('R','var') && exist('S', 'var')     A2 = pi*R^2; A3 = S^2;     fprintf('Area of a circle:  A2 =  %5g \n', A2);     fprintf('Area of a square:  A3 =  %5g \n', A3); elseif isempty(W) && isempty(L) && isempty(R)     A3 = S^2;     fprintf('Area of a square:  A3 =  %5g \n', A3); elseif isempty(S) && isempty(W) && isempty(L)     A2 = pi*R^2;     fprintf('Area of a circle:  A2 =  %5g \n', A2); else exist('W','var') && exist('L','var') && exist('R','var') && exist('S','var')     A1=W*L; A2 = pi*R^2; A3 = S^2;     fprintf('Area of a rectangle:  A1 =  %5g \n', A1);     fprintf('Area of a circle:  A2 =  %5g \n', A2);     fprintf('Area of a square:  A3 =  %5g \n', A3); else     fprintf('You need to ENTER some dimensions! \n') end

After fixing the errors, with the following entries, these outputs are displayed in the Command window:

Width of a rectangle:          1 Length of a rectangle:         1 Radius of a circle:            1 Side length of a square:       1 Area of a rectangle:  A1 =     1 Area of a circle:  A2 =  3.14159 Area of a square:  A3 =      1

Exercise 13

Fix the five errors in the following script:

%% Assessing the student performances clc; clearvars SP =input('Enter the student grade:  '); if SP <65     disp('Student Grade is  F ') elseif SP>=66 && SP<=71 disp('Student Grade is  D ') elseif SP>71 && SP<=81     disp('Student Grade is  C ') elseif SP>82 && SP<87     disp('Student Grade is  B ') else     disp('Student Grade is  A ') end

After fixing the errors and running the script with inputs [65, 71, 81, 82, 87 87.5] in sequential order, the following outputs should be shown in the Command window:

Enter the student grade:  65 Student Grade is  F Enter the student grade:  71 Student Grade is  C Enter the student grade:  81 Student Grade is  C Enter the student grade:  82 Student Grade is  B Enter the student grade:  87 Student Grade is  B Enter the student grade:  87.5 Student Grade is  A

Exercise 14

Write a script (program) that computes all solutions:

  • (1) But displays only real solutions of these third-order polynomial equations for any values of a, b, c, and f: i) x3 + bx2 + cx = 0; ii) ax3 + f = 0; iii) ax3 + cx = 0; iv) x2 + bx + c = 0.

  • (2) But displays only complex solutions of these equations for any values of a, b, c, and f: i) ax2 + c = 0; ii) ax3 + f = 0; iii) ax2 + bx + c = 0

Exercise 15

Write a script (program) that computes the volume and weight of the model that may have a form of cube, cylinder, and rectangular prism. Users need to enter (via input prompt) the necessary geometric dimensions of the model and enter or select material properties (density) from the given data (aluminum, copper, and steel) in your script. Your script has to write all computed and user input data sets into an external file called RESULTS.txt with explanatory comments in it along with numerical data.

Exercise 16

Edit and correct the following given script to display the current date and time correctly in the Command window:

Format short e T=clock; fprintf('This year is: %n4 \n', T(1)) if T(2)==1  sprintf('It is: %f4 -st month of the year:  %n4 \n', T(2),T(1)) elseif T(2)==2  sprintf('It is: %f4 -nd month of the year:  %n4 \n', T(2),T(1)) elseif T(3)==3  sprintf('It is: %f4 -rd month of the year:  %n4 \n', T(2),T(1)) else  sprintf('It is: %f4 -th month of the year:  %n4 \n', T(2),T(1)) end sprintf('current time is: %lo o"clock %l0 min \n', T(4), T(5)) sprintf('and %s secs \n', (T(6)))

Your corrected script should display the current date and time in the following format:

It is: 11 - day of the 6-th month of the year:  2014 current time is: 15 o"clock 3 min  and 17.136 secs

Exercise 17

Given: y(x, t) = y0 sin (kx − ωt) is the solution of the wave equation where \( k=\frac{2\pi }{\lambda } \) is the wave number, ω = 2πf is the angular frequency, and λ is the wave length.

  • Write an anonymous function with a function handle to compute the values of y(x, t) with input arguments of k, ω,x, t.

  • Write an inline function to compute the values of y(x, t) with input arguments of k, ω,x, t.

  • Write a function file to compute the values of y(x, t) with input arguments of k, ω,x, t.

Exercise 18

The equation for a power factor of a series resistor-capacitor (RC) circuit with no inductance is \( \mathit{\cos}\ \delta =\frac{RC\omega}{\sqrt{1+{\left( RC\omega \right)}^2}} \).

  • Write an anonymous function with the function handle to compute the values of δ with the input arguments of R, C, and ω.

  • Write an inline function to compute the values of δ with the input arguments of R, C, and ω.

  • Write a function file to compute the values of δ with the input arguments of R, C, and ω, and plot δ versus ω.

Exercise 19

The equation for charge in a resistor-inductance-capacitor (RLC) circuit in a series is determined by Kirchhoff’s law: \( L\ddot{q}+R\dot{q}+\frac{q}{C}={E}_{max} coscos\ \omega t \).

An R L C circuit diagram based on the Kirchhoff's law.
  1. 1.

    Write an anonymous function with a function handle for solving the given second-order differential equation for q(t) with the input arguments of R, L, C, ω, and t.

  2. 2.

    Write an inline function necessary for solving the given second-order differential equation for q(t) with the input arguments of R, L, C, ω, and t.

  3. 3.

    Write a function file necessary for solving the given second-order differential equation for q(t) with the input arguments of R, L, C, ω, and t.

  4. 4.

    Create a Simulink model to simulate the given RLC system.

Exercise 20

The acceleration of a skydiver is determined by the following:

$$ a=g\left(1-\frac{v^2}{3600}\right) $$

where g = 9.81 m/s2.

  1. 1.

    Write an anonymous function to compute a as a function of speed v.

  2. 2.

    Write a function file to compute a as a function of speed v and plot a versus v.

  3. 3.

    Create a Simulink model to simulate an acceleration of a skydiver.

  4. 4.

    Compute the terminal speed for a skydiver.

Exercise 21

A truck of mass m is accelerated from rest at t = 0 with constant power P along a level road. The speed of the truck as a function of time is given by \( v(t)={\left(\frac{2P}{m}\right)}^{\frac{1}{2}}\sqrt{t} \).

If x = 0 at time t = 0, the position function x(t) is given by \( x(t)={\left(\frac{8P}{9m}\right)}^{\frac{1}{2}}\sqrt{t^3} \),

where P = 550 kW and m = 15000 kg.

  1. 1.

    Write a function handle to compute the speed of the truck v(t) as a function of time t.

  2. 2.

    Write an inline function to compute the position of the truck from the function x(t) as a function of time t.

  3. 3.

    Build plots of x(t)versust, v(t) versus t in two separate plot figures.

Exercise 22

In a crash test, a car traveling 100 km/h (28 m/sec) hits an immovable concrete wall. We can treat this problem in general with the approximation that the car body is one piece, despite that different parts of the car when it hits the wall will accelerate differently. In fact, upon impact, the center of the car moves forward less than half of its length. Let’s assume that the stopping distance of the car upon hitting the wall until full stop is 0.72 m. Time to full stop will be equal to \( \varDelta t=\frac{\varDelta x}{{\textrm{v}}_{ave}}=\frac{0.72}{0.5{\textrm{v}}_0+0.5\textrm{v}}=\frac{0.72}{0.5\textrm{v}}=\frac{0.72}{14}=0.051\ \sec . \)

The average acceleration of the car until full rest is equal to \( a=\frac{\varDelta v}{\varDelta t}=\frac{v_0-v}{\varDelta t}=-\frac{v}{\varDelta t}=-544.44\ m/ se{c}^2 \)

Note that this is about 55g, which means very high acceleration (deceleration) that takes over very large amount of energy from inertia forces and converts it into heat. Write a function file to compute a as a function of Δx (for different front bumper types) and v (for all cases, take v0 = 0) for a crash test of any type of cars with different traveling speeds of v.

Exercise 23

Create a function file (called Ex23.m) taking one input argument (the planted year of the maple tree that is four-digit integer: 0 ... 2018) and the two output variables AGE (calculated age of the maple tree) and NOTE (with regard to the age of the maple tree), as well as a warning/message box with notes.

  1. 1.

    If the planted year of the tree is before 1000, the outputs are NOTE = "CANNOT be TRUE", AGE = [ ] (empty) and also an error box with the note "Check Your Entry.”

  2. 2.

    If the planted year of a tree is in between [1000...1918], the outputs are NOTE = "NEED to be PROTECTED", AGE = [] (computed age with respect to the current year) and a warning dialog box with the note "Maple Tree is to be Under Protection.”

  3. 3.

    If the planted year of a tree is in between [1919 ...2000], the outputs are NOTE = "WELL fit", AGE = [] (computed age with respect to the current year) and a message box with the note “GOOD one for a timber”;.

  4. 4.

    If the planted year of a tree is in-between [2001 ...2018], the outputs are NOTE = "TOO young", AGE = [] (computed age with respect to the current year) and a message box with the note “TOO young for a timber.”

Exercise 24

The spiral of Archimedes (also called the Archimedean spiral) is a spiral curve (named after the 3rd-century BC Greek mathematician Archimedes). The equation of the spiral is written in the polar coordinate system by the following equation: r = a + , where r is the distance from the origin and θ is the angle of that point in radians with respect to the origin. The parameters a, b in the equation are real numbers that control the spiral and the distance between successive spiral turnings, respectively.

  1. 1.

    Compute the spiral of Archimedes for \( \theta =0:\frac{\pi }{10000}:13\pi, a=-1.25,b=-2.25 \)with a vectorization method.

  2. 2.

    Compute the spiral of Archimedes for \( \theta =0:\frac{\pi }{10000}:13\pi, a=-1.25,b=-2.25 \)with the [for ... end] and [while ... end] loops without memory allocation.

  3. 3.

    Compute the spiral of Archimedes for \( \theta =0:\frac{\pi }{10000}:13\pi, a=-1.25,b=-2.25 \) with the [for ... end] and [while ... end] loops with memory allocation.

  4. 4.

    Compare the computation efficiencies in (2) and (3) against (1) using [tic ... toc].

Exercise 25

Create a function file (called Ex25.m) taking four input variables (n, bn, ∆x, L) and three output variables: f(x), ALL _ cell, ALL _ struct.

Compute this series: \( f(x)={\sum}_{n=1}^{\infty}\frac{b_n\mathit{\sin}\left(\left(2n-1\right)\pi x\right)}{2L} \) using [for, end] loop control statements. Take n = 1 : 11, bn = [−5...5], x = [0...L], L = 10. \( \Delta x=\frac{L}{2000}. \)

ALL _ cell is a cell array composed of f(x), x, bn.

ALL _ struct is a structure array composed of f(x), x, bn, ALL _ cell.

Exercise 26

Create a function file (called Ex26.m) taking one input variable (k) and one output variable (S).

Compute a total sum of these series: \( 10+35+65+110+\dots ={\sum}_{m=0}^{55}\left(10\ast {2.5}^k\right) \). Compute the total sum using the [while, end] and [for, end] loop control statements.

  1. 1.

    Halt the computation process when the sum is larger than 2.5 ∗ 1018 and display in the Command window at what iteration step the computation is halted and the computed sum of the series.

  2. 2.

    Display the difference between the computed sum of series and 2.5 ∗ 1018.

  3. 3.

    Display the final sum and the iteration number as integers, but collect all of the sums (S) from every step.

Exercise 27

Write a script file to compute the solutions of the third-order polynomial a3x3 + a2x2 + a1x = 0 for any given values of its coefficients a1, a2, a3 with a user prompt input and by using the conditional statements [if, elseif, else, end]. Include in your script to print out solutions of the polynomial in the external *.dat file in the correct data formats including complex values.