8kyu Basic Mathematical Operations
1 題目說明:
函式做基本的數學四則運算,依運算子 return 數值結果
函式接受 3 個參數:
- operation(string/char)
- value1(number)
- value2(number)
Examples(Operator, value1, value2) --> output
('+', 4, 7) --> 11
('-', 15, 18) --> -3
('*', 5, 5) --> 25
('/', 49, 7) --> 7
2 code:
export function basicOp(operation: string, value1: number, value2: number): number {
// Good luck!
if(operation === '+') {
return value1 + value2
} else if (operation === '-') {
return value1 - value2
} else if (operation === '*') {
return value1 * value2
} else { // 可再優化: 除法之外的運算子
return value1 / value2 // 可再優化: 除法 分母不可為0
}
}
3 修改code
題目 定義函式回傳值類型為數字,比如返回0或者NaN (Not a Number),以表明當出現無效操作時的特殊情況。確保函式在所有可能的程式路徑上都返回一個數字。
wiki 除以零是一個沒有定義的值。
export function basicOp(operation: string, value1: number, value2: number): number {
// Good luck!
if(operation === '+') {
return value1 + value2;
} else if (operation === '-') {
return value1 - value2;
} else if (operation === '*') {
return value1 * value2;
} else if (operation === '/') {
if (value2 === 0) { //除法 分母不能為0
return "NaN"; // 或者 return 0;
}
return value1 / value2;
} else {
return NaN; // 或者 return 0;
}
}
console.log(typeof NaN) //number
4 ChatGTP提醒:
一些邊界條件需要考慮進去。
若 operation 不是"+"
、"-"
、"*"
或"/"
時,函式就沒有返回值。這樣在 TypeScript 中會被解釋為函式可能返回 undefined。
加上一個 else 區塊來返回一個預設值或者拋出一個錯誤。
除法,若 value2 是 0 的話,這樣會導致除以零的錯誤。
5 進行優化:
- Switch Statement: 使用 switch 語句來取代多個 if-else。可使程式碼更易讀且更簡潔。
- 錯誤處理: 增加錯誤處理,當操作符號不是你預期的四種之一時,可返回一個錯誤訊息。
優化 函式回傳值 type annotation: 聯合型別 Union Types : number | string
才能 return 字串
export function basicOp(operation: string, value1: number, value2: number): number | string {
switch(operation) {
case '+':
return value1 + value2;
case '-':
return value1 - value2;
case `*`:
return value1 * value2;
case '/':
if (value2 === 0) { //除法 分母不能為0
return "Cannot divide by zero";
}
return value1 / value2;
default:
return "Invalid operation"; //加減乘除之外的運算子
}
}
優化 函式回傳值 type annotation: 聯合型別 Union Types : number | string
6 語法
throw
throw
是一個 JavaScript / TypeScript 中的關鍵字,用於拋出一個異常(或錯誤)。
當程式執行到 throw 時,它會立即停止並跳轉到最近的能夠處理這個錯誤的程式碼塊。若沒有處理這個錯誤的程式碼,這個異常將會被傳遞到呼叫這個函式的地方,或者如果這個函式是頂層函式的話,它將會成為一個未處理的全局異常。
在上面的代碼中,throw new Error("Invalid operation"); 就是當 operation 不是 '+', '-', '*' 或 '/' 任何一個時拋出的錯誤。這樣做的好處是可以清楚地指示這是一個錯誤情況,並且如果程式碼中有合適的地方來處理這個錯誤,可以讓程式流程更加清晰。
else {
throw new Error("Invalid operation");
}
7 submit code
export function basicOp(operation: string, value1: number, value2: number): number {
// Good luck!
if(operation === '+') {
return value1 + value2;
} else if (operation === '-') {
return value1 - value2;
} else if (operation === '*') {
return value1 * value2;
} else if (operation === '/') {
if (value2 === 0) { //除法 分母不能為0
return NaN; // 或 return 0;
}
return value1 / value2;
} else {
return NaN; // 或 return 0;
}
}
8 RECAP
- if/ else => switch
- else {...} 要考慮4個加減乘除外,可能的因素
- 除法 分母不能為0。 除以零是一個沒有定義的值。
有錯誤回傳 字串型別
- 函式回傳值的type annotation為 聯合型別 Union Types
: number | string
return "Invalid operation"
返回一個錯誤訊息。throw new Error("Invalid operation")
拋出一個錯誤,而不是讓函式可能返回 undefined。
有錯誤回傳 number型別
return NaN
return 0
switch 用法 (補)
throw 用法 (補)
9 觀摩
const ops = {
"+": (l, r) => l + r,
"-": (l, r) => l - r,
"*": (l, r) => l * r,
"/": (l, r) => l / r,
}
export const basicOp = (operation: keyof typeof ops, value1: number, value2: number): number => (
ops[operation](value1, value2)
)
- operation 的類型被限制為 ops 物件的鍵(keyof typeof ops),也就是
+, -, *, /
這些字串中的一個。
basicOp 函式的主要功能是通過 ops 物件 根據指定的操作符號調用對應的函式來執行運算。它會從 ops 中找到與 operation 相符的函式,然後將 value1 和 value2 傳遞給該函式進行運算,最終返回運算結果。
這樣的寫法非常簡潔和有效率,因為它使用了物件來組織和映射不同的操作符號和對應的函式,使得代碼易於閱讀和維護。
測試
import {basicOp} from "./solution";
import {assert} from "chai";
describe('basicOp', () => {
it('basic tests', () => {
assert.strictEqual(basicOp('+', 4, 7), 11);
assert.strictEqual(basicOp('-', 15, 18), -3);
assert.strictEqual(basicOp('*', 5, 5), 25);
assert.strictEqual(basicOp('/', 49, 7), 7);
})
})