Crystal 有所謂的控制運算式,用來控制程式的執行方式,它們會接受真值或假值。 有一類運算子可以用來產生真值或假值,這些稱為相等與比較運算子。
控制哪些程式碼會執行、哪些不會的控制運算式主要有兩種,也就是決定會執行哪個分支。
這兩種是:if和unless運算式。
比較運算子用來比較值並回傳 true 或 false。這類運算子要求兩個型別相同的值才能比較。如果兩個值的型別不同,編譯器會拋出錯誤。
以下是比較運算子清單,以及它們產生 true 時的範例:
| 方法 | 說明 | 範例 |
|---|---|---|
| < | 小於 | 4 < 5 |
| <= | 小於或等於 | 4 <= 4 |
| > | 大於 | 3 > 1 |
| >= | 大於或等於 | 2 >= 2 |
相等運算子和比較運算子類似,但用來檢查兩個值是否相等。
==運算子會檢查兩個值是否相等,包括值的型別。如果兩個值相同,就回傳 true,否則回傳 false。
==運算子可以拿任何型別的值和任何其他型別的值比較。
!=的運作方式相同,但值不相等時回傳 true,相等時回傳 false。
if敘述if敘述用來檢查給定的條件是真值還是假值。如果條件為真值,if敘述裡的程式碼就會執行。if敘述以 end關鍵字結尾。
if 1 == 1
puts "1 is equal to 1"
end
# => 1 is equal to 1
if 1 > 2
puts "1 is greater than 2"
end
# => no output
unless敘述unless敘述的運作方式和 if敘述非常相似,但如果條件為假值,它就會執行 unless敘述裡的程式碼。
unless 1 == 1
puts "1 is not equal to 1"
end
# => no output
unless 1 > 2
puts "1 is not greater than 2"
end
# => 1 is not greater than 2
else敘述else敘述可以和 if、unless敘述搭配使用。如果 if分支或 unless分支沒有執行,就會執行 else敘述。
即使 `else`分支可以和 `unless,`搭配使用,也不建議這麼做,因為會降低可讀性。
建議改用帶有 else 分支的 `if !condition`。
if 1 == 1
puts "1 is equal to 1"
else
puts "1 is not equal to 1"
end
# => 1 is equal to 1
unless 1 < 2
puts "1 is not greater than 2"
else
puts "1 is greater than 2"
end
# => 1 is greater than 2
elsif敘述可以和 if 敘述搭配使用。如果 if 分支沒有執行,而且 elsif敘述的條件為真值,就會執行 elsif敘述。
elsif敘述可以串接在一起,第一個為真值的條件會被執行。
if 敘述最後也可以有一個 else 敘述,如果前面的敘述都沒成立,就會執行它。
if 1 != 1
puts "1 is not equal to 1"
elsif 1 > 2
puts "1 is greater than 2"
else
puts "1 is not equal to 1 and 1 is not greater than 2"
end
# => 1 is not equal to 1 and 1 is not greater than 2
當變數被指定成不同型別時,變數會同時帶有這兩種型別。這是因為編譯器不知道哪個分支會被執行。這種多重指定也稱為 union,會在之後的概念中介紹。以下範例可以看到這種情況:
if 1 == 1
a = 1
else
a = "1"
end
typeof(a) # => Int32 | String
Crystal 有三元運算子,也就是單行的 if-else 敘述:condition ? expression_if_truthy : expression_if_falsey
1 == 1 ? puts("1 is equal to 1") : puts("1 is not equal to 1")
# => 1 is equal to 1
在這個練習中,我們要為核子反應爐開發一套簡單的控制系統。
反應爐要產生電力,就必須處於_臨界_狀態。如果反應爐的狀態低於臨界,就可能受損;如果反應爐的狀態超過臨界,就可能過載,導致爐心熔毀。我們希望能降低熔毀的機率,並正確地管理反應爐的狀態。
以下三個任務都與撰寫程式碼來維持理想的反應爐狀態有關。
控制系統第一件要做的事,就是檢查反應爐是否處於平衡的臨界狀態。當反應爐滿足以下條件時,就稱為處於臨界:
請實作方法Reactor.criticality_balanced?,它接受以克氏溫標計量的temperature和neutrons_emitted作為參數,並在符合臨界條件時回傳true,不符合時回傳false。
Reactor.criticality_balanced?(750, 600)
# => true
反應爐開始產生電力之後,就必須判斷它的效率。效率可以分為 4 個等級:
green -> 效率達 80% 以上,orange -> 效率低於 80%,但至少 60%,red -> 效率低於 60%,但仍有 30% 以上,black -> 效率低於 30%。百分比數值可以用(generated_power/theoretical_max_power)*100計算,其中generated_power = voltage * current。請注意,百分比數值通常不會是整數,因此務必留意<和<=比較的正確用法。
請實作方法Reactor.reactor_efficiency,它有三個參數:voltage、current和theoretical_max_power。這個函式應回傳反應爐的效率等級:"green"、"orange"、"red"或"black"。
Reactor.reactor_efficiency(200,50,15000)
# => "orange"
你的最後一項任務,是建立一套失效安全機制,以避免過載與爐心熔毀。這套機制會判斷反應爐是低於、等於還是高於理想的臨界門檻。接著就能透過將控制棒插入(或移出)反應爐,來提升、降低或停止臨界程度。
請實作方法Reactor.fail_safe(),它接受 3 個參數:以克氏溫標計量的temperature、neutrons_produced_per_second和threshold,並輸出反應爐的狀態代碼。
如果temperature * neutrons_produced_per_second小於threshold的 90%,請輸出狀態代碼 "LOW",表示必須移除控制棒才能產生電力。
如果temperature * neutrons_produced_per_second落在threshold加減 10% 的範圍內,反應爐就處於_臨界_狀態,此時應輸出狀態代碼 "NORMAL",表示反應爐處於最佳狀態,控制棒也位於理想位置。
如果temperature * neutrons_produced_per_second不在上述範圍內,反應爐正邁向爐心熔毀,必須傳遞狀態代碼 "DANGER",以立即關閉反應爐。
temperature = 1000
neutrons_produced_per_second = 30
threshold = 5000
Reactor.fail_safe(temperature, neutrons_produced_per_second, threshold)
# => "DANGER"