Simple math statements in bash in a for loop

30,394

Solution 1

Here's a decent solution:

for i in {1..20}
do
   for j in {1..20}
   do
       echo "scale = 3; sqrt($i*$i + $j*$j)" | bc
   done
done

Output will be:

1.414
2.236
3.162
2.236
[...etc...]

Solution 2

Arithmetic expansion needs $((...)) notation, so something like:

echo $((i*i + j*j))

However, bash only uses integers so you may need to use an external tool such as dc.

E.g.

dc -e "18k $i $i * $j $j * + v p"

Solution 3

Shell math can be done in several ways.

echo $(( i*i + j*j ))
echo $[ i*i + j*j ]
expr "$i" '*' "$i" '+' "$j" '*' "$j"

However, this can only handle integer arithmetic. Instead, you can use bc:

echo "scale = 5; sqrt( $i*$i + $j*$j)" | bc

Change scale to the number of decimal places desired.

Solution 4

#!/bin/bash
for i in {1..20}; do
    for j in {1..20}; do
        echo 5k$i $i\* $j $j\*+vp | dc
    done
done

Solution 5

Use double paren to evaluate a variable.

variableA=$((variableB*variableC))

Only for ints though.

Share:
30,394
physicsmichael
Author by

physicsmichael

Particle physics in my rear view mirror; data science in my headlights. My mother tongue is python, but I used C++ often while I was stuck/blessed with ROOT in physics. I dabble in Tex, Arduino, Raspi, bash, cluster computing, and more!

Updated on July 13, 2020

Comments

  • physicsmichael
    physicsmichael almost 4 years

    I'm quite new to bash scripting and usually avoid it all costs but I need to write a bash script to execute some simple things on a remote cluster. I'm having problems with a for loop that does the following:

    for i in {1..20}
    do
        for j in {1..20}
        do
            echo (i*i + j*j ) **.5  <--- Pseudo code!
        done
    done
    

    Can you help me with this simple math? I've thrown $'s everywhere and can't write it properly. If you could help me understand how variables are named/assigned in bash for loops and the limitations of bash math interpretation (how do you do the square root?) I'd be very grateful. Thanks!

  • dustmachine
    dustmachine over 14 years
    You're probably missing the .. between your 1 and 20 in your {1..20} range
  • ephemient
    ephemient over 14 years
    Weird, it should work in any POSIX bc. What if you use dc? i.e. dc -e "5 k $i $i * $j $j * + v p"
  • ephemient
    ephemient over 14 years
    "almost certainly"? Certainly not standard on any Linux distribution I've seen. Perhaps you mean *BSD?
  • physicsmichael
    physicsmichael over 14 years
    Bah. I shorted the j loop so it wouldn't flood the screen and introduced a typo.
  • wallyk
    wallyk over 14 years
    ksh is on Fedora and CentOS.
  • ephemient
    ephemient over 14 years
    It's available as a package, but not part of the default install. Most Linux systems use Bash as the default shell; the BSDs tend to gravitate around various non-GNU shells.
  • Chris Johnsen
    Chris Johnsen over 14 years
    My variant: printf "%s %s 10kd*rd*+vp" "$i" "$j" | dc