題目描述

讓我們來開始使用Bash腳本來進行簡單的數值計算吧!輸入一個包含「+」、「-」、「*」、「/」和括號的數學算式,並輸出計算結果。



原題網址

輸入格式

輸入只有一行,為一個包含「+」、「-」、「*」、「/」和括號的數學算式,數字的部份可以為浮點數,且不會超過999。

輸出格式

輸出算式的計算結果,小數部份固定取到小數點後三位。

範例輸入1

5+50*3/20 + (19*2)/7

範例輸出1

17.929

範例輸入2

-105+50*3/20 + (19^2)/7

範例輸出2

-45.929

範例輸入3

(-105.5*7+50*3)/20 + (19^2)/7

範例輸出3

22.146

解題概念

題目要求要進行算式計算,還要能符合四則運算的規則,看起來似乎十分困難,而且Bash內建的計算功能不是只能支援整數嗎?

在Bash腳本中其實可以將參數傳給外部指令以達成特定功能,如果要進行一些算術計算的話,可以使用「bc」指令來協助。直接將算式透過標準輸入傳給「bc」指令,「bc」指令就會透過標準輸出回傳結果。

「bc」指令常搭配「-l」參數使用,讓「bc」指令可以使用標準數學函式庫作運算,計算結果才會是精確的。「bc」指令常搭配「echo」指令使用,透過管線導向方式將算式透過「echo」指令來輸出到標準輸出,再使用管線導向將標準輸出導向到「bc」指令的標準輸入。用法如下:

echo 算式 | bc -l

例如:

echo "2 + 6/8" | bc -l

輸出結果為:

2.75000000000000000000

若要控制「bc」指令輸出結果的精確度,可以先設定「scale」的大小。若要讓「bc」指令輸出到小數點後1位,可以將「scale」的大小設為「1」,例如:

echo "scale = 1; 2 + 6/8" | bc -l

輸出結果為:

2.7

為什麼答案不是2.8呢?不是應該要四捨五入嗎?因為「scale」是用無條件捨棄的方式來省略小數的哦!若要有類似四捨五入的功能,可以搭配「printf」指令來使用。若要讓「bc」指令輸出到小數點後1位,可以將「%.1f」作為「printf」的格式化參數字串。用法如下:

printf "%.1f" $(echo 算式 | bc -l)

例如:

printf "%.1f" $(echo 2 + 6/8 | bc -l)

輸出結果為:

2.8

那如果將算式最後多加0.1呢?答案會是2.9嗎?

例如:

printf "%.1f" $(echo 2 + 6/8 + 0.1 | bc -l)

輸出結果為:

2.8

結果居然還是「2.8」!?如果不省略小數的話,計算出來不是「2.850000」嗎?為什麼省略小數之後是「2.8」呢?這是因為「printf」指令遇到「5」時會隨便進位或是捨去,所以之前「2.75」會變成「2.8」,而「2.85」還是「2.8」。

再實測幾個例子:

printf "%.1f" 2.35
printf "%.1f" 2.45
printf "%.1f" 2.55
printf "%.1f" 2.65
printf "%.1f" 2.75
printf "%.1f" 4.35
printf "%.1f" 4.45
printf "%.1f" 4.55
printf "%.1f" 4.65
printf "%.1f" 4.75

結果為:

2.3
2.5
2.5
2.7
2.8
4.3
4.4
4.6
4.7
4.8

補充一點,並不是所有程式語言或是腳本語言實作出來類似「printf」的功能,都是遇到「5」就隨便進位或是捨去的。舉個例子,C/C++和Java程式語言就是使用純粹的「四捨五入」哦!

參考答案

#!/bin/bash
read r
printf "%.3f" $(echo $r | bc -l)