Prepare calculations and chart results with Bash Math, Shell Style
Tutorials – Shell Math
While Bash is not the most advanced environment for doing and visualizing math, its power will surprise you. Learn how to calculate and display your results with shell scripts.
In this series' previous installments on Bash scripting [1, 2, 3, 4], I have explained how to use data structures, flow control commands, and testing operators. Now, I will show you how to handle numberrelated tasks with shell scripts.
Before getting started, I want to discuss the strengths and weaknesses of doing math inside shell scripts.
Bash cannot do floatingpoint math or plotting. As for speed, fast calculations of any kind have never been a selling point of Unix shells. When it comes to performance, there have been many, much better solutions since before C and Fortran. Today, with the right libraries, even other scripting languages are better choices if raw execution speed is your main requirement.
The same applies to interactivity and user interfaces, especially when your want to quickly visualize how changing some input data or formula impacts a math function or changes the solution to some problem. If this is what you need, a LibreOffice spreadsheet or tools like Genius [5] or Graph [6], for actually studying math, may be much more effective solutions.
The real strengths of doing calculations in a shell script are "human efficiency" and "glue logic." While a shell script will most likely run slower than equivalent code in other languages, writing that code as a Bash script will very likely be faster. Runtime performance only really matters with code that you must run many times, possibly every day.
For an average desktop user, however, most problems that require writing code will be oneoff issues, different enough from each other to require different code each time. In all those cases, getting working code quickly saves much more human time than writing the fastest possible code. Shell scripts are made to order for this kind of need, even when numbercrunching is required.
Efficiency is even greater when you consider what I call the shell script's glue logic. Shell scripts are born as allpurpose tools that can easily launch, and connect with pipes, any other commandline program. Consider any problem spread across different areas, such as file management and actual numeric calculations of any kind: If you can quickly implement the complete solution as one script, what you gain in implementation time and selfdocumentation greatly outweighs what you may lose in raw performance.
Variables
One of shell scripts' advantages is that you do not need to explicitly declare the variable type. At the same time, the Bash interpreter has native support only for integer arithmetic. Therefore, the first best practice to deal with numeric variables is to explicitly declare their nature with the i
(integer) switch:
declare i MYCOUNTER=10
This will reduce the possibility of unnoticed errors, because the script will abort if you try to assign to $MYCOUNTER
any value that is not an integer number. For the same reason, you should really declare as readonly all the numeric constants you want to use:
declare r TIMEOUTVALUE=100
Operators
Integer arithmetic's basic operations are supported with the same operators you would use in calculations done by hand, with the same relative precedences: first exponentiation (**
), then multiplication (*
) and division (/
), sum and subtraction, and finally remainder or modulo (%
):
X=8 X=$(( $X / 2 )) Y=3 Z=$(( X ** Y )) Q=$(( Z % 5 ))
In the example above, Z
would be equal to 64, and Q
to four, which is exactly the remainder of 64 divided by five. The modulo operator is often used to determine whether a number is odd or even. Other essential operators are those for automatic increment or decrement, which have the highest precedence of all:
X=4 echo $(( X++ )) echo $X
The first echo command would print 4, and the second would print 5. This happens because the value of $X
is incremented by one unit, but only after passing its previous value to echo
. The automatic decrement operator ($X
) works in the same way.
I already introduced the Bash syntax for arithmetic expressions in this series' first installment "Shell Variables", but here is a quick recap. The examples above use the most flexible syntax, the double parentheses. Inside the double parentheses, you can execute any mathematical expression with or without spaces and use all variants of all operators. If you prefer (or simply want to copy code from older scripts), however, you can also evaluate arithmetic expressions with the let
and expr
keywords. Both of these commands:
let "X /= 2" X=`expr $X / 2`
divide by two the current value of X
.
Floatingpoint Math with bc
The Bash interpreter has no builtin commands to handle floatingpoint calculations or complex mathematical functions like those for trigonometry. In practice, this has never been a problem, thanks to the commandline, scriptready calculator (and language) known as bc
.
bc
supports arbitrary precision numbers, for which you can separately define both "length" and "scale." The bc
man page [7] defines length as "the total number of significant decimal digits in a number." The scale, instead, is the total number of decimal digits after the decimal point.
When you tell it to load its math library with the l
option, bc
can use functions like c(x)
, l(x)
and sqrt (x)
to calculate cosine, natural logarithm and the square root of x
respectively. bc
can be used interactively at the prompt, but what makes it really powerful is the capability to load code from files or standard input. In the first case, bc
executes code from all the files passed to it in the order they are listed one line at a time. In the second case, you can pipe to bc
one or more lines of code generated on the fly, according to the current values of some variables, as in this small example:
#> Y=55 #> X=`echo "scale=8; c($Y/39)"  bc l` #> echo $X .15985120
A common, quickanddirty usage of bc
in Bash scripts is to round up decimal numbers to the lower, or higher integer, as shown here:
X=4.5 echo "($X + 0.5)/1"  bc 5 echo "($X + 0.49)/1"  bc 4 X=4.51 echo "($X + 0.49)/1"  bc 5
These examples also highlight that you should be careful with the rounding value. bc
's internal programming language supports internal variables and arrays and comments in the same syntax as the C language:
/* any text between these characters is a comment */
It also supports control flow structures and print statements. Due to space constraints, I can't cover the language in more detail here. However, it is simple and similar enough to Bash that if you have already mastered the previous installments of this series, it will not be a problem for you (also see the detailed bc
man page [7]).
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Direct Download
Read full article as PDF:
Price $2.95
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Find SysAdmin Jobs
News

LibreOffice 7.5 has Arrived and is Loaded with New Features and Improvements
The favorite office suite of the Linux community has a new release that includes some visual refreshing and new features across all modules.

The Next Major Release of Elementary OS Has Arrived
It's been over a year since the developers of elementary OS released version 6.1 (Jólnir) but they've finally made their latest release (Horus) available with a renewed focus on the user.

KDE Plasma 5.27 Beta Is Ready for Testing
The latest beta iteration of the KDE Plasma desktop is now available and includes some important additions and fixes.

Netrunner OS 23 Is Now Available
The latest version of this Linux distribution is now based on Debian Bullseye and is ready for installation and finally hits the KDE 5.20 branch of the desktop.

New Linux Distribution Built for Gamers
With a Gnome desktop that offers different layouts and a custom kernel, PikaOS is a great option for gamers of all types.

System76 Beefs Up Popular Pangolin Laptop
The darling of opensourcepowered laptops and desktops will soon drop a new AMD Ryzen 7powered version of their popular Pangolin laptop.

Nobara Project Is a Modified Version of Fedora with UserFriendly Fixes
If you're looking for a version of Fedora that includes thirdparty and proprietary packages, look no further than the Nobara Project.

Gnome 44 Now Has a Release Date
Gnome 44 will be officially released on March 22, 2023.

Nitrux 2.6 Available with Kernel 6.1 and a Major Change
The developers of Nitrux have officially released version 2.6 of their Linux distribution with plenty of new features to excite users.

Vanilla OS Initial Release Is Now Available
A stock GNOME experience with ondemand immutability finally sees its first production release.