National Yang Ming Chiao Tung University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try a Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

1

Local AI

--

Uedu Code

--

陽明交大 AQI 69 24°C PM2.5 26
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 13

Math 物件

亂數、取整數、三角函數與環狀排列
Interaction實作 15 minute(s)

Learning Objectives

  • 使用 Math 物件的常數與方法:PI、max、min、abs、sqrt、pow
  • 分辨 floor、ceil、round、trunc 四種取整數的方法,特別是負數的結果
  • 用 Math.random 產生指定範圍的亂數整數,並說明亂數是偽隨機
  • 用角度換算弧度,使用 sin、cos、atan2
  • 用 cos、sin 把元素排成一圈,並用 % 實作環狀佇列

Math:內建的數學工具箱

Math 是 JavaScript 內建的物件,收集了常用的數學常數與函式。它和 Date、Array 不一樣: 不是建構函式,不能 new Math();所有屬性和方法都直接用 Math.名稱 取用。

常數/方法 意思 例子
Math.PI、Math.E 圓周率 π、自然常數 e 3.141592653589793
Math.max(a, b, …)、Math.min(…) 最大、最小值 Math.max(3, 9, 1) → 9
Math.abs(x) 絕對值 Math.abs(-8) → 8
Math.sqrt(x) 平方根 Math.sqrt(81) → 9
Math.pow(x, y) x 的 y 次方,和 x ** y 相同 Math.pow(2, 10) → 1024
Math.floor(x) 往下取整數(往負無限大) Math.floor(-4.7) → -5
Math.ceil(x) 往上取整數(往正無限大) Math.ceil(-4.7) → -4
Math.round(x) 四捨五入;剛好 .5 時往正無限大的方向 Math.round(-2.5) → -2
Math.trunc(x) 直接去掉小數部分(往 0) Math.trunc(-4.7) → -4

Math.max 收的是一個一個的引數,不是陣列:要找陣列的最大值,寫 Math.max(...arr) 先展開。 要顯示到小數第幾位,用數字的 toFixed(位數),它回傳的是字串。

取整數:floor、ceil、round、trunc

每一列依序是:原本的數、floor、ceil、round、trunc。正數時 floor 和 trunc 一樣,看到 -4.7 那一列就不一樣了;也注意 -2.5 四捨五入的結果。

亂數:Math.random

Math.random() 回傳一個 0(含)到 1(不含) 之間的小數。電腦用數學公式算出「看起來隨機」的數字, 這叫偽隨機(pseudorandom);一般的遊戲、抽籤、洗牌夠用,但不能用在密碼、驗證碼這類需要安全性的地方 (那要用 crypto.getRandomValues())。

要得到 min 到 max 之間的整數(兩端都含),步驟是:

Math.random()                          // 0 ≤ r < 1
Math.random() * (max - min + 1)        // 0 ≤ … < 範圍內整數的個數
Math.floor(…)                          // 0、1、…、max - min
Math.floor(…) + min                    // min、…、max

用 Math.floor 而不是 Math.round:round 會讓兩端的數字出現機率只有中間的一半。

這一課的逐步執行動畫為了可以重現,亂數使用固定的種子,所以每次播放、每個人看到的結果都一樣。 在真正的瀏覽器裡,Math.random() 每次執行的結果都不同。

骰子、擲硬幣與隨機挑選

randomInt(1, 6) 被呼叫 8 次,每次看右邊框架的回傳值。注意結果一定在 1 到 6 之間:Math.random() * 6 是 0 到 5.99…,floor 後是 0 到 5,再加 1。

想一想:取整數與亂數

1.

下面的程式會印出什麼?

console.log(Math.floor(-3.2), Math.trunc(-3.2), Math.ceil(3.2));
2.

要產生 10 到 20 之間的整數(10 和 20 都可能出現),哪一個寫法正確?

3.

下面的程式會印出什麼?

const scores = [72, 95, 88];
console.log(Math.max(...scores), Math.min(scores));
第 1 次作答

三角函數:先把角度換成弧度

做動畫、遊戲、畫圖表時,常需要「往某個角度走一段距離」,這時就會用到三角函數。 Math.sin、Math.cos、Math.tan 的參數是弧度(radian),不是角度:

const rad = deg * Math.PI / 180;   // 180° 等於 π 弧度
Math.sin(90 * Math.PI / 180);      // 1
方法 意思
Math.sin(x)、Math.cos(x)、Math.tan(x) 正弦、餘弦、正切,x 是弧度
Math.asin(x)、Math.acos(x) 反正弦、反餘弦,x 超出 -1~1 時得到 NaN
Math.atan(x) 反正切,結果在 -π/2 到 π/2 之間
Math.atan2(y, x) 從原點到點 (x, y) 的角度(弧度),y 在前、x 在後

浮點數有誤差:Math.sin(Math.PI) 不是剛好 0,而是 1.2246467991473532e-16(非常接近 0)。 要顯示結果時用 toFixed 控制位數,比較兩個小數時不要直接用 ===。

常見角度的 sin 與 cos

每一圈先把角度換成弧度,再算 sin 與 cos,用 toFixed(3) 顯示到小數第三位。最後兩行看浮點數誤差與 atan2。

把元素排成一圈

圓心在 (cx, cy)、半徑是 r 的圓上,角度 θ 的那一點座標是:

x = cx + r * Math.cos(θ);
y = cy + r * Math.sin(θ);

要把 N 個點平均排在圓上,第 i 個點的角度是 2 * Math.PI * i / N(一圈是 2π,平均分成 N 份)。

網頁的座標和數學課的座標有一點不同:y 軸往下是正的。所以角度 0 在圓心的右邊,角度增加時是順時針轉。 想讓第一個點在正上方,把每個角度都減掉 Math.PI / 2(90°)。

算出 4 個點的座標

圓心 (150, 150)、半徑 100,四個點的角度依序是 0、π/2、π、3π/2。注意第二個點的 y 是 250:網頁的 y 軸往下。

互動練習:環狀排列

這段程式用 Math.cos、Math.sin 把 6 個圓點排成一圈。依任務修改 JavaScript,每次改完按「執行」,看圓點怎麼移動。

另一種「環狀」:環狀佇列

投影片的「環狀排列」還介紹了一種資料結構:佇列(queue)是先進先出(FIFO,First In First Out)的集合, 像排隊一樣,只能從後端(rear)加入、從前端(front)取出。用陣列的 push 和 shift 就能做出簡單的佇列:

const queue = [];
queue.push('A');     // 從後端加入
queue.shift();       // 從前端取出 'A'

環狀佇列(circular queue)使用固定大小的陣列,頭尾相連:索引走到最後一格之後回到 0。 做法是每次移動索引時用 % 取餘數:rear = (rear + 1) % size。這樣取出元素之後空出來的格子可以重複使用,不必移動其他元素。

要分辨佇列「空」還是「滿」有兩種常見作法:投影片的作法是永遠空一格(front 與 rear 相同時是空,rear 的下一格是 front 時是滿, 所以最多只能放 size - 1 個);下面的範例另外用 count 記錄個數,四格都能用。

環狀佇列:用 % 繞回開頭

大小為 4 的佇列先放入 A、B、C、D(E 放不進去),取出 A、B 之後再放入 F、G:看第 14 行 rear 從 3 變成 0,F、G 放進了前面空出來的格子。

想一想:三角函數與環狀排列

1.

要計算 60° 的 sin 值,哪一個寫法正確?

2.

下面的程式會印出什麼?

const angle = Math.PI / 2;
const x = Math.round(100 + 50 * Math.cos(angle));
const y = Math.round(100 + 50 * Math.sin(angle));
console.log(x, y);
3.

下面的程式會印出什麼?

const size = 5;
let i = 3;
for (let k = 0; k < 4; k++) {
  i = (i + 1) % size;
}
console.log(i);
第 1 次作答

實作:圓上的點

完成 pointOnCircle(cx, cy, r, deg):給圓心、半徑與角度,回傳物件 { x, y },兩個座標都四捨五入成整數。完成後會印出 0°、90°、180°、270° 四個點。

你的輸出
預期輸出

重點精華回顧

  • Math 是內建物件,不能 new;常數 Math.PI、Math.E,方法 max、min、abs、sqrt、pow 直接呼叫。
  • 取整數:floor 往下、ceil 往上、round 四捨五入、trunc 去掉小數;負數時結果各不相同。
  • Math.random() 是 0(含)到 1(不含)的偽隨機小數;min 到 max 的整數用 Math.floor(Math.random() * (max - min + 1)) + min。
  • 三角函數的參數是弧度:角度 * Math.PI / 180;浮點數有誤差,顯示時用 toFixed。
  • 圓上的點:x = cx + r * cos(θ)、y = cy + r * sin(θ);N 個點平均分配,角度是 2π * i / N;網頁的 y 軸往下。
  • 佇列是先進先出;環狀佇列用 (index + 1) % size 讓索引繞回開頭,重複使用空出來的格子。
這一課完成了!
Next lesson:時間與計時器
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。