Topics in this lab
One of the big differences between scientific computing and other branches of computer science is that scientific computing deals with floating point numbers to a much greater extent. One consequence of this is that the number of significant digits that appear in a result that we print out if very important.
Back to the top
A quick way to change the formatting behavior in Matlab's command line is to use the format key word. To see approximately five digits displayed, we can use the short as a keyword argument to format.
format short pi
ans = 3.1416
This format is what is called fixed point formatting. The decimal place is fixed in place, regardless of the value of the number, and approximately five significant figures are shown, with four digits after the decimal place. If we scale the number to make it either larger or smaller, we see that the location of the decimal point remains fixed, as long as the total number of digits does not exceed 7, (roughly) or drop below about 2.
ans = 0.3142
ans = 0.0314
ans = 0.0031
ans = 31.4159
ans = 314.1593
Using the keyword long produces roughly the same results, but with about 15 digits after the decimal place.
ans = 3.141592653589793
ans = 0.314159265358979
ans = 0.031415926535898
ans = 31.415926535897931
In all cases, the decimal place shifts to the right or left in the
However, as soon as we scale the number by larger values, we see that the formatting changes to exponential notation, to accommodate the fact that more than four digits would be needed before the decimal, or the value would require more than two leading zeros.
format short 1000*pi
ans = 3.1416e+03
format long 1000*pi
ans = 3.141592653589793e+03
In both cases, the formatting changed to a floating point
notation (sometimes called exponential or scientific
notation). The decimal point "floats" so that the there is exactly one
digit before the decimal and four or 16 after the decimal.
To explicitly specify scientific notation, use a trailing "e" for either the long or short versions of the format statement. With this keyword, you will always get exponential notation, regardless of the magnitude of the number.
format short e
ans = 3.1416e+00
ans = 3.1416e-01
ans = 3.1416e+01
format long e
ans = 3.141592653589793e+00
ans = 3.141592653589793e-01
ans = 3.141592653589793e+01
In general, the format statement should only be used for quick formatting
at the command line, and should never be used in a script to print out
results of a calculation. As you would see after some experimentation
the rules for formatting using format are not clear, and the result is somewhat
unpredictable. Furthermore, there seems to be no way to print a numbers
like $10000\pi$ or $\pi/10000$ using fixed point notation, or to
specify that exactly 8 digits after the decimal should be shown.
We can completely control the formatting behavior of numbers and strings by using the fprintf command, which we discuss next.
Back to the top
In scientific computing, the manner in which we format output (tables of
numbers for example) depends on what we plan to do with those numbers. If
all you want to see is whether a number is positive or negative, you might
only need very few digits. But if you want to see how how many digits of
accuracy you get in a particular approximation, you might want the full 16
digits available. Often, when working with measurements of physical quantities,
you want your displayed values to reflect the number of significant
digits or level or precision in your measurements.
For this reason, it is useful to have a flexible way of presenting numerical output. The fprintf command is particularly useful. It does not take arguments in the traditional sense, but instead uses format strings to indicate how text and numbers should be printed.
Here is how we could use the fprintf to format the values from the examples above. This time, we will specify exactly how many digits appear after the decimal, and whether to use fixed or floating point notation.
Fixed point notation, using 8 digits after the decimal.
Notice that in each case, we get exactly 8 digits after the decimal
place, and that the decimal remains fixed in the location needed to
accurately represent the value. Also notice, however, that the number of significant
figures we show varies with each example above. When we just printed
$\pi$, we saw 9 significant figures (1
before and 8 after the decimal). But when printing $\pi/1000$, we saw only 6 significant figures
and when printing $\pi/1000$, we see 12
Here are a few more extreme examples to illustrate this behavior.
fprintf('%16.8f\n',pi/1e12); % looks like 0, but it isn't!
fprintf('%24.8f\n',1e12*pi); % Lots of digits of pi. Are they all correct?
Here is how we might use fprintf to print a table of numbers. In this example, we print the same number in several different ways.
x = -2e2 + 4e2*rand(1,5); % Numbers in [-200,200] fprintf('XX|XXXXX.XX|XXXXXXX.XXXXXXXX|XXX.XXXXXXXXXXXXXXXXe+NN|\n'); for i = 1:5, fprintf('%2d|%8.2f|%16.8f|%24.16e|\n',i,x(i), x(i),x(i)); end;
XX|XXXXX.XX|XXXXXXX.XXXXXXXX|XXX.XXXXXXXXXXXXXXXXe+NN| 1| -33.09| -33.09317237| -3.3093172366252190e+01| 2| -180.14| -180.13822787| -1.8013822786970314e+02| 3| 161.09| 161.08644397| 1.6108644396611243e+02| 4| 177.91| 177.91487589| 1.7791487588865840e+02| 5| -3.65| -3.65436301| -3.6543630127680160e+00|
The first argument to fprintf in this example is
a string. This string contains four format strings, e.g.
'%16.8f' and '%24.16e'.
The first value in the format string is the field width and the
second value is the number of digits after the decimal place to display.
The field width is exactly the number of characters between the
vertical bars ('|'), including any the decimal point,
a possible '-' or '+'
(a minus or plus sign) and any characters needed to represent floating
point numbers (e.g. the 'e+02' in the above example).
In the above example, the format strings 'd','f', and 'e' are used. These are the most common, and are to be used with integers, fixed point formatting, and floating point (scietific notation) formatting, respectively.
Notice what can happen if we don't format properly. In following examples, we show several formatting "mistakes", and a way to correct them.
We are using a fixed point notation, but are not plotting enough digits to see that our number is not zero.
a = 1.456e-10; fprintf('|XXXXXXXXXX|\n'); fprintf('|%10.4f|\n',a); % Using 'f' in this case only shows zero digits fprintf('|%10.3e|\n',a); % Show non-zero digits
|XXXXXXXXXX| | 0.0000| | 1.456e-10|
Here, we have again not specified enough digits, and the print statement is rounding up to the nearest value that can be printed using the format string we have specified.
b = 4.0098734; fprintf('|XXXXXXXXXX|\n'); fprintf('|%10.2f|\n',b); % Not wrong, but just be aware that fprintf rounds up
|XXXXXXXXXX| | 4.01|
In this case, we are using the integer format string 'd', but our number is not an integer. The fprintf statement then reverts to a default format %12.6e.
c = 7.631; fprintf('|XXXXXXXXXX|\n'); fprintf('|%10d|\n',c); % The integer format string ('d') is over-ridden. fprintf('|%10.3f|\n',c); % Use the 'f' format string instead.
|XXXXXXXXXX| |7.631000e+00| | 7.631|
And when we do not specify a field width sufficiently wide to contain the number of digits that should be printed out, the specified field width is overrun.
d = -456745e8; fprintf('|XXXXXXXXXX|\n'); fprintf('|%10f|\n',d); % Field width too small; decimal digits are shown fprintf('|XXXXXXXXXXXXXXX|\n'); fprintf('|%15.0f|\n',d); % Increase field width; don't show decimal digits
|XXXXXXXXXX| |-45674500000000.000000| |XXXXXXXXXXXXXXX| |-45674500000000|
Finally, if we fail to take into account the width needed for the extra characters involved in the formatting of a floating point number, we also overrun the specified field width.
e = pi*1e-4; fprintf('|XXXXXXXXXX|\n'); fprintf('|%10.9e|\n',e); % Field width not large enough fprintf('|XXXXXXXXXXXXXXX|\n'); fprintf('|%15.9e|\n',e); % Increase size of field.
|XXXXXXXXXX| |3.141592654e-04| |XXXXXXXXXXXXXXX| |3.141592654e-04|
Back to the top
The command fprintf also works on arrays. In this case, the format string is applied to each entry of the array.
x = -1 + 2*rand(1,5); fprintf('|XXXXXXXX|\n'); fprintf('|%8.4f|\n',x); % x is an array
|XXXXXXXX| | -0.0215| | -0.3246| | 0.8001| | -0.2615| | -0.7776|
One final formatting tip is the use of the "string" formatting to list a set of values in a nice way. Here is a simple example.
fprintf('%16s %10.1f\n','Temperature (K)',301.3); fprintf('%16s %10.2e\n','Energy (J)',1.24e6); fprintf('%16s %10.2f\n','Density (kg/m3)',1.21); fprintf('%16s %10.2f\n','Pressure (bar)',2.13);
Temperature (K) 301.3 Energy (J) 1.24e+06 Density (kg/m3) 1.21 Pressure (bar) 2.13
By using the string format string 's', we can right justify the label for each value, which leads to a nicely formatted table.
Back to the top
- Use the fprintf to print out
the following numbers.
a = 5 b = 14.567 c = exp(12) d = 2^(-12)
Your output should look exactly like the second line in the output displayed below :
|XXXXX|XXXXXXXXXX|XXXXXXXXXXXX|XXXXXXXXXXXXXX| | 5| 14.567| 1.6275e+05|3.05175781e-05|
The 'X's are placed as a guide and don't need to be printed. Count the field width of the formatted string to make sure you have correctly spaced the digits before and after the decimal, and any additional characters needed for scientific notation.
Compare your results with the solutions.
Back to the top
Get the code
Do you want to try the above code fragments on your own? Download the Matlab script that produces this page here. (lab_12.m)
Published with MATLAB® 8.5