用不同的加权百分比计算成绩,并以 bash 的形式输出最终成绩



我需要编写一个 bash shell 脚本,询问用户他们的名字和 4 个不同百分比的测试分数,然后计算他们的总成绩并输出他们的字母等级。

值如下:

Assignments 30%
Midterm 30%
quiz 10%
Final 30%

在读取变量后,我尝试将变量按 (30/100) 进行多类型化,但我无法让 bash 接受多行算术。到目前为止,我只能将它们全部相加并除以 4。在这一点上我迷失了任何帮助,感谢任何帮助

echo "What is your name?"
read name 
echo "What is your score on the Assignment?"
read s1 
echo "What is your score on the Quiz?"
read s2 
echo "What is your score on the Midterm Exam?"
read s3 
echo "What is your score on the Final Exam?"
read s4 

total=$(expr $s1 + $s2 + $s3 + $s4) 
avg=$(expr $total / 4) 

if [ $avg -ge 80 ] 
then 
echo "$name's grade is an A"
elif [ $avg -ge 70 ] 
then 
echo "$name's grade is a B" 
elif [ $avg -ge 60 ] 
then 
echo "$name's grade is a C"
elif [ $avg -ge 50 ] 
then 
echo "$names's grade is a D"
else 
echo "$name's grade is an F" 
fi

根据我上面的评论,您可以做几件事。首先使用POSIX算术运算符(( ... ))而不是古代expr。接下来,由于 bash 仅提供整数数学,因此为了使用百分比,您必须将百分比乘以100然后除以100以获得total。你不除以4,你的百分比已经考虑到加权分数达到 100%。此外,在 bash 中,您必须依靠像bc这样的浮点实用程序来处理所有浮点计算,包括得出avg的除法。

但是,当您在if then elif ... else语句中比较avg时,仅凭这一点并不能消除舍入误差(例如,将79.9视为79)。使用bc获取79.9您仍然需要一种方法来正确处理舍入,以便从小于79.5但大于或等于78.5的任何值79.5(或更好)和79获得80

值得庆幸的是,printf -v提供了一种方便的方法,可以将转换结果存储为变量并处理舍入,因为它使用了 C-print 转换逻辑。例如,要保存按bc转换avg的结果,然后正确舍入(保存在变量名rounded中),您可以执行以下操作:

total=$((s1 * 30 + s2 * 30 + s3 * 10 + s4 * 30))
avg=$((total / 100))  ## not used but saved for output demonstration below
printf -v rounded "%.0f" $(printf "scale=2; $total/100n" | bc)

总而言之,您可以做到:

#!/bin/bash
echo "What is your name?"
read name 
echo "What is your score on the Assignment?"
read s1 
echo "What is your score on the Quiz?"
read s2 
echo "What is your score on the Midterm Exam?"
read s3 
echo "What is your score on the Final Exam?"
read s4 
total=$((s1 * 30 + s2 * 30 + s3 * 10 + s4 * 30))
avg=$((total / 100)) 
printf -v rounded "%.0f" $(printf "scale=2; $total/100n" | bc)
if [ "$rounded" -ge 80 ] 
then 
echo "$name's grade is an A"
elif [ "$rounded" -ge 70 ] 
then 
echo "$name's grade is a B" 
elif [ "$rounded" -ge 60 ] 
then 
echo "$name's grade is a C"
elif [ "$rounded" -ge 50 ] 
then 
echo "$names's grade is a D"
else 
echo "$name's grade is an F" 
fi

为了确认四舍五入他的处理正确,您可以添加以下保存rounded的简单printf,例如添加:

printf "ntotal: %dnavg  : %dnrounded avg: %dnn" 
"$total" "$avg" "$rounded"

然后要确认,输入分数将导致一个数字,如果未正确四舍五入将导致"B"而不是"A"(您以80分自由地给出),例如

示例使用/输出

$ bash student.sh
What is your name?
John
What is your score on the Assignment?
78
What is your score on the Quiz?
80
What is your score on the Midterm Exam?
81
What is your score on the Final Exam?
81
total: 7980
avg  : 79
rounded avg: 80
John's grade is an A

使用case语句

您可能还需要考虑使用简单的case ... esac语句来消除长链if then elif then elif then ...语句,这将大大清理问题。例如,您可以将整个if then elif ... else集合替换为

printf "%s's grade is an '" "$name"
case "$rounded" in
100 | [89]? ) echo "A'";;
7? ) echo "B'";;
6? ) echo "C'";;
5? ) echo "D'";;
*  ) echo "F'";;
esac

使用/输出case的示例

$ bash student.sh
What is your name?
John
What is your score on the Assignment?
78
What is your score on the Quiz?
80
What is your score on the Midterm Exam?
80
What is your score on the Final Exam?
80
total: 7940
avg  : 79
rounded avg: 79
John's grade is an 'B'

仔细看看,如果你有问题,请告诉我。

最新更新