1

So I have this script I've been working on to get input for grades and then it'll calculate them with the weight of each section. At the end, it'll output a letter grade depending on the calculated grade. My code is fine until the if-else statement, where I'll start getting errors of an illegal number in the condition of each if-else statement.

#!/bin/sh
#Calculate weighted grade and output grade letter

echo "What is your total Lab/Assignments grade?" read labGrade echo "What is your Midterm grade?" read midtermGrade echo "What is your total Quizzes grade?" read quizGrade echo "What is your Final Exam grade?" read finalGrade

weightedLab=echo "0.25*$labGrade" | bc weightedMidterm=echo "0.30*$midtermGrade" | bc weightedQuiz=echo "0.15*$quizGrade" | bc weightedFinal=echo "0.30*$finalGrade" | bc

totalGrade=echo "$weightedLab + $weightedMidterm + $weightedQuiz + $weightedFinal" | bc

if [ $totalGrade -ge 90.00 ] then echo "Your total grade is an A+!" elif [ $totalGrade -ge 85.00 -a $totalGrade -le 89.00 ] then echo "Your total grade is an A!" elif [ $totalGrade -ge 80.00 -a $totalGrade -le 84.00 ] then echo "Your total grade is an A-!" elif [ $totalGrade -ge 76.00 -a $totalGrade -le 79.00 ] then echo "Your total grade is a B+" elif [ $totalGrade -ge 72.00 -a $totalGrade -le 75.00 ] then echo "Your total grade is a B" elif [ $totalGrade -ge 68.00 -a $totalGrade -le 71.00 ] then echo "Your total grade is a B-" elif [ $totalGrade -ge 64.00 -a $totalGrade -le 67.00 ] then echo "Your total grade is a C+" elif [ $totalGrade -ge 60.00 -a $totalGrade -le 63.00 ] then echo "Your total grade is a C" elif [ $totalGrade -ge 56.00 -a $totalGrade -le 59.00 ] then echo "Your total grade is a C-" elif [ $totalGrade -ge 50.00 -a $totalGrade -le 55.00 ] then echo "Your total grade is a D" else echo "Your total grade is an F" fi

What is your total Lab/Assignments grade?
100
What is your Midterm grade?
100
What is your total Quizzes grade?
100
What is your Final Exam grade?
90
./A2.sh: 20: [: Illegal number: 97.00
./A2.sh: 23: [: Illegal number: 97.00
./A2.sh: 26: [: Illegal number: 97.00
./A2.sh: 29: [: Illegal number: 97.00
./A2.sh: 32: [: Illegal number: 97.00
./A2.sh: 35: [: Illegal number: 97.00
./A2.sh: 38: [: Illegal number: 97.00
./A2.sh: 41: [: Illegal number: 97.00
./A2.sh: 44: [: Illegal number: 97.00
./A2.sh: 47: [: Illegal number: 97.00
Your total grade is an F

How can I change the code to properly compare the values?

Gyro
  • 13
  • Bash only supports integer arithmetic For real number support (what you are calling floats), use a shell such as ksh93 or zsh.. – fpmurphy Apr 02 '21 at 21:58
  • We prefer examples that are as small as possible.  (Also, when you're debugging something, you should try to narrow it down by cutting the program down smaller and smaller.) You could have demonstrated this problem with a one-line example: [ 97.00 -ge 90.00 ]. – G-Man Says 'Reinstate Monica' Apr 13 '21 at 06:21

2 Answers2

2

Bash doesn't do floating point arithmetic.

But since you don't need arbitrary scale, you just calculate with the numbers scaled up by a hundred, so that you're left with only integers, e.g.

lab=100 midterm=70 quiz=90 exam=80
total=$((25*lab + 30*midterm + 15*quiz + 30*exam))
if (( total >= 8000 )); then
    echo "you scored at least 80! (actually $(( total / 100 )))"
fi

Or you could use some other tool that does work with floating point numbers, see:
How to do integer & float calculations, in bash or other languages/frameworks?

ilkkachu
  • 138,973
1

First of all: bash can only handle integer numbers. So you need to make use of an external too for the floating point comparison.

A simple way would be using bc, which outputs 0 on FALSE statements, and 1 on TRUE statements, comparison operators are <, <=, >, >=, ==, and !=. They work as you know them.

 echo '1 > 2' | bc -l
 0
 echo '1 <= 2' | bc -l
 1

Thus change your tests to

 [ $(echo "$totalGrade >= 90.00" | bc -l) -eq 1 ]

and so on.

Hint 1

elif [ $totalGrade -ge 80.00 -a $totalGrade -le 84.00 ]

In this expression the -a $totalGrade -le 84.00 is redundant, as the IF-loop is evaluated in the same order as in the script, so the $totalGrade -le 84.00 is already taken care of once $totalGrade -ge 85.00 is FALSE.

Hint 2 What happens if the grade is 84.5? Your evaluations miss these values.

ilkkachu
  • 138,973
FelixJN
  • 13,566