Skip to content

while 條件迴圈:不知道要跑幾次?

上一節,你學會了 for 迴圈:告訴電腦「這件事做 N 次」。但如果你不知道 N 是多少呢?

想像你在玩「猜數字」遊戲:電腦心裡想了一個數字,你一直猜,猜對為止。你不知道要猜幾次,可能 3 次就中了,也可能猜 20 次。這種「不知道要跑幾次,跑到某個條件成立為止」的情境,for 迴圈就搞不定了。

為什麼?因為 for i in range(???) 那個 ??? 你根本填不出來。

這就是 while 迴圈登場的時候。

📷 圖 4:for 迴圈已知次數 vs while 迴圈未知次數的四格漫畫(AI 製圖)

📷 圖 4:for 迴圈已知次數 vs while 迴圈未知次數的四格漫畫(AI 製圖)

💡 📋 學習目標

看完這一節,希望你將能夠:

  1. 了解 while 迴圈跟 for 迴圈的差異(已知次數 vs 未知次數)
  2. 學會 while 迴圈的語法和執行邏輯
  3. 知道「無窮迴圈」是什麼、怎麼避免
  4. 用 Trace Table 追蹤 while 迴圈的每一步
  5. 解一道經典的 3N+1 猜想 Judge 題 ✧。٩(ˊᗜˋ)و✧*。

你已經知道 for 迴圈適合「確切知道要跑幾次」的場景。但現實中有太多情況是「跑到滿足某個條件為止」。這種需求催生了第二種迴圈。

while 迴圈:跑到條件不成立為止

概念溯源:為什麼需要兩種迴圈?

為什麼要用生活場景來解釋?因為 while 的邏輯跟你每天做的事其實一模一樣。

想想你每天早上的鬧鐘:鬧鐘響了,你按掉繼續睡。鬧鐘又響了,你又按掉。一直到你終於覺得「好吧,再不起來真的要遲到了」,你才起床。

你不知道自己會按幾次貪睡鍵(有時候 2 次,有時候 5 次),但你知道「起床的條件」:快遲到了。

(有些人的條件是「媽媽掀被子」,那個比任何程式都有效 ╮(╯_╰)╭ )

這就是 while 迴圈的邏輯:「只要條件成立,就一直做某件事。直到條件不成立,才停下來。」

語法長什麼樣?

while 的語法比 for 還簡單:

python
while 條件:
    要重複做的事

來看一個具體的例子:從 5 倒數到 1:

python
n = 5
while n > 0:
    print(n)
    n = n - 1

輸出:

5
4
3
2
1

讓我們拆解執行流程:

  1. 一開始 n = 5
  2. 檢查條件 n > 0 → 5 > 0 是 True → 進入迴圈
  3. 印出 5,然後 n = n - 1 → n 變成 4
  4. 回到步驟 2,再次檢查條件
  5. 重複,直到 n 變成 0,0 > 0 是 False → 離開迴圈

Trace Table:看清 while 的每一步

跟上一節一樣,我們用 Trace Table 來展開:

第幾次檢查 n > 0n 的值輸出n 更新後
1True (5 > 0)554
2True (4 > 0)443
3True (3 > 0)332
4True (2 > 0)221
5True (1 > 0)110
6False (0 > 0)

第 6 次檢查時,n 已經是 0,條件 0 > 0 為 False,迴圈結束。

`while` vs `for` 的核心差異

  • for i in range(n):你提前知道要跑幾次(n 次),Python 自動幫你計數
  • while 條件:你不知道要跑幾次,Python 每次迴圈開始前檢查條件,True 就繼續,False 就停

「老師,那上面那個倒數的例子,用 for i in range(5, 0, -1) 也可以吧?」

沒錯!如果你知道次數,用 for 通常更簡潔。while 真正厲害的地方,是處理那些你事先不知道要跑幾次的問題。等一下的 Judge 題會讓你深刻體會到這一點。

小心!無窮迴圈

在那之前,有一個超級重要的坑要先提醒你:

⚠️ 無窮迴圈(Infinite Loop)

如果你忘記在迴圈裡更新條件變數,條件永遠是 True,程式就會永遠跑下去,直到你手動停止。

python
n = 5
while n > 0:
    print(n)
    # ❌ 忘記寫 n = n - 1!
    # n 永遠是 5,5 > 0 永遠是 True
    # 結果:無限印出 5 5 5 5 5...

修正版本:

python
n = 5
while n > 0:
    print(n)
    n = n - 1  # ✅ 每次減 1,n 最終會變成 0,條件變 False

📌 寫 while 的三步口訣

  1. 初始化:在迴圈前設定條件變數的初始值
  2. 條件:寫好 while 後面的判斷條件
  3. 更新:在迴圈裡面更新條件變數,確保條件最終會變成 False

少了第 3 步 = 無窮迴圈 (゚Д゚;)

📷 圖 5:無窮迴圈的噩夢四格漫畫(AI 製圖)

📷 圖 5:無窮迴圈的噩夢四格漫畫(AI 製圖)

好了,語法學完、陷阱也知道了。接下來用一道超有趣的數學題來實戰!


你已經學會了 while 的語法和注意事項。現在來挑戰一道真正需要 while 才解得了的題目。這道題你根本不可能用 for 寫,因為你完全不知道迴圈要跑幾次。

Judge 解題實戰:3N+1 猜想

這道題的數學背景很有趣:它是一個到今天都還沒被證明的猜想,連數學家都還在研究 Σ(゚Д゚)

題目說明

  • Input:一行輸入,一個正整數 N(N ≥ 2)
  • Output:根據以下規則不斷變換 N,直到 N 變成 1,輸出總共經過幾步

變換規則:

  • 如果 N 是偶數 → N = N ÷ 2(整數除法)
  • 如果 N 是奇數 → N = 3 × N + 1
  • 重複直到 N = 1

範例

InputOutput
68
27111

老師的建議

先試著自己動手!提示:這是一個典型的「不知道要跑幾次」的問題,while 是你的好朋友。

卡關了再看解答!

Step 1:分析 IPO

  • I(Input):讀取一個正整數 N
  • P(Process):按照「偶數除 2、奇數乘 3 加 1」的規則不斷變換 N,直到 N 變成 1。同時數步數
  • O(Output):印出步數

關鍵問題:你不知道要變換幾步才會到 1。以 N = 6 為例,序列是 6 → 3 → 10 → 5 → 16 → 8 → 4 → 2 → 1,共 8 步。但以 N = 27 為例,竟然要 111 步才到 1!

這就是為什麼我們需要 while:因為步數完全不可預測。

Step 2:先畫 Trace Table

在寫程式碼之前,先用 N = 6 手動走一遍:

步數N(執行前)N 是偶數?執行操作N(執行後)
166 // 23
233 × 3 + 110
31010 // 25
455 × 3 + 116
51616 // 28
688 // 24
744 // 22
822 // 21

N 變成 1,停下來。總共 8 步。

Step 3:寫出程式碼

有了追蹤表的思路,翻譯成 Python 就很直接了:

python
# I:讀取輸入
n = int(input())

# P:用 while 迴圈不斷變換
steps = 0
while n != 1:
    if n % 2 == 0:
        n = n // 2
    else:
        n = 3 * n + 1
    steps = steps + 1

# O:印出步數
print(steps)

逐行解讀:

  1. n = int(input()) — 讀取正整數 N
  2. steps = 0 — 初始化步數計數器
  3. while n != 1: — 只要 N 還不等於 1,就繼續跑
  4. if n % 2 == 0: — 用 %(取餘數)判斷 N 是偶數還是奇數
  5. n = n // 2 — 偶數就除以 2(整數除法)
  6. n = 3 * n + 1 — 奇數就乘 3 加 1
  7. steps = steps + 1 — 每跑一次迴圈就加 1 步
  8. print(steps) — 迴圈結束後,印出總步數

Step 4:在 Judge 上測試

提交看看。N = 6 應該輸出 8,N = 27 應該輸出 111

常見錯誤排查

  • while n > 1 寫成 while n != 0

    N 永遠不會變成 0(3N+1 規則下,N 最終會到 1 然後停下)。條件要寫 n != 1

  • n / 2 而不是 n // 2

    / 是浮點除法(結果是小數),// 是整數除法。用 / 的話 n 會變成 3.0 之類的浮點數,後續的 % 運算可能出問題。

  • 忘記 steps = steps + 1

    最後印出的步數永遠是 0。

自己動手試試!

一道搞定了?再來兩道 (ノ◕ヮ◕)ノ*:・゚✧

位數計算器

問題情境:小茵是班上的班長,每學期都要負責整理全班同學和家長的通訊錄。這次她收到了一大堆朋友和家長傳來的電話號碼,長短不一,有些是十位數的手機號碼、有些是八位數加區碼的市話、有些甚至只有三四位數的公司分機。每次手動一個一個數位數實在太累了,她想寫一個小程式,讓電腦自動判斷任何一串數字到底有幾位數,這樣就能快速驗證號碼格式是否正確,省下大量人工核對的時間。請你幫她寫一支程式:輸入一個非負整數 N,計算 N 總共有幾位數並印出來。

🔍 思考引導

🔀 試著補完這張流程圖...

下面的流程圖有些步驟被 ??? 遮住了,試著想想看遮住的地方應該填什麼:

輸入格式: 第一行:一個非負整數 N(0 ≤ N ≤ 10^9)

輸出格式: 一行,印出 N 的位數(特殊情況:N = 0 時輸出 1)

範例一

輸入輸出
123455

範例二

輸入輸出
01

範例說明

  1. 第一步:N = 12345,不是 0,所以從 count = 0 開始計數,進入迴圈
  2. 第二步:N = 12345 > 0,count 變成 1,N 變成 12345 // 10 = 1234
  3. 第三步:N = 1234 > 0,count 變成 2,N 變成 1234 // 10 = 123
  4. 第四步:N = 123 > 0,count 變成 3,N 變成 123 // 10 = 12
  5. 第五步:N = 12 > 0,count 變成 4,N 變成 12 // 10 = 1
  6. 第六步:N = 1 > 0,count 變成 5,N 變成 1 // 10 = 0
  7. 第七步:N = 0,迴圈結束,印出 count = 5

老師的提示

注意 N = 0 是特殊情況——如果讓 0 直接進迴圈,count 永遠不會累加,你可能需要在進入迴圈之前先想好怎麼處理它。


數字反轉器

問題情境:阿博最近迷上了一個數字鏡像遊戲:把一個數字的每一位順序倒過來,看看會變成什麼。例如 12345 倒過來是 54321,100 倒過來是 1(前導零不算)。他覺得這個遊戲很有趣,常常在上課無聊的時候拿計算紙玩,但數字一旦超過五、六位數,用手算就很容易出錯。於是他決定用剛學會的程式能力來解決這個問題,寫一支程式讓電腦自動完成翻轉,不管輸入多大的數字都能瞬間得到答案。請你幫阿博寫程式:輸入一個正整數 N,輸出它的數字反轉結果。

🔍 思考引導

🧩 把大問題拆成小問題...

  1. 第一步 — 取出最後一位:用 % 運算子可以取出 N 目前的最後一位數字
  2. 第二步 — 移除最後一位:用 // 運算子可以把最後一位去掉,讓 N 縮短一位
  3. 第三步 — 拼接反轉結果:把剛取出的數字「接」到目前反轉結果的最後面,想想看要怎麼在數學上做到這一點
  4. 第四步 — ???:什麼時候應該停止?停止條件是什麼?

輸入格式: 第一行:一個正整數 N(1 ≤ N ≤ 10^9)

輸出格式: 一行,印出 N 的數字反轉結果(不輸出前導零)

範例一

輸入輸出
1234554321

範例二

輸入輸出
1001

範例說明

  1. 第一步:N = 12345,reversed = 0,開始迴圈
  2. 第二步:12345 % 10 = 5,reversed = 0 × 10 + 5 = 5,N = 12345 // 10 = 1234
  3. 第三步:1234 % 10 = 4,reversed = 5 × 10 + 4 = 54,N = 1234 // 10 = 123
  4. 第四步:123 % 10 = 3,reversed = 54 × 10 + 3 = 543,N = 123 // 10 = 12
  5. 第五步:12 % 10 = 2,reversed = 543 × 10 + 2 = 5432,N = 12 // 10 = 1
  6. 第六步:1 % 10 = 1,reversed = 5432 × 10 + 1 = 54321,N = 1 // 10 = 0
  7. 第七步:N = 0,迴圈結束,印出 reversed = 54321

老師的提示

反轉數字的關鍵在於如何把新取出的數字「拼」到結果最後面——想想看,如果 reversed 目前是 32,要把 1 拼到最後面,數學上要怎麼算?


加總達標步數

問題情境:小婷從高一開始就養成了存零用錢的好習慣,她給自己訂了一個簡單的規則:第一個月存 1 元、第二個月存 2 元、第三個月存 3 元,依此類推,每個月比上個月多存 1 元。最近她看上了一款限量版的繪圖板,需要存到一筆目標金額才買得起。她很好奇,按照這個存錢計畫,到底至少要存幾個月,累計存款才能達到或超過她設定的目標金額 S 元?與其自己拿紙筆慢慢加,不如寫一支程式讓電腦幫忙算。請你幫小婷完成這支程式,輸入目標金額 S,輸出她最少需要存幾個月。

🔍 思考引導

🔀 試著補完這張流程圖...

下面的流程圖有些步驟被 ??? 遮住了,試著想想看遮住的地方應該填什麼:

輸入格式: 第一行:一個正整數 S(1 ≤ S ≤ 5000)

輸出格式: 一行,印出加了幾個整數才讓總和達到或超過 S

範例一

輸入輸出
104

範例二

輸入輸出
11

範例說明

  1. 第一步:S = 10,total = 0,count = 0,n = 0,開始迴圈
  2. 第二步:total = 0 < 10,n 變成 1,total = 0 + 1 = 1,count = 1
  3. 第三步:total = 1 < 10,n 變成 2,total = 1 + 2 = 3,count = 2
  4. 第四步:total = 3 < 10,n 變成 3,total = 3 + 3 = 6,count = 3
  5. 第五步:total = 6 < 10,n 變成 4,total = 6 + 4 = 10,count = 4
  6. 第六步:total = 10,已達到 S = 10,迴圈結束,印出 count = 4

老師的提示

while total < s: 作為條件,每輪加入下一個整數並讓計數器加一。注意:更新「下一個整數」(讓它加一)不要忘記,否則會無窮迴圈。


最大公因數(GCD)

問題情境:阿達在音樂課學到「節拍」的概念後,想用數學來解決一個問題:兩段音樂的節拍分別是 A 拍和 B 拍,如果要把它們合在一起演奏,就需要找到一個能整除兩者的最大公同拍數,這樣才能讓兩段旋律完美對齊。老師告訴他,這其實就是求最大公因數的問題。阿達上網查了資料,發現有一個古老又優雅的方法叫「輾轉相除法」,據說是古希臘數學家歐幾里得兩千多年前就發明的,至今仍被廣泛使用。請你幫阿達寫程式:輸入兩個正整數 A 和 B,用輾轉相除法求出它們的最大公因數。

🔍 思考引導

💭 如果用數學來表達...

gcd(a,b)=gcd(b, amodb)

其中 amodba 除以 b 的餘數。這個公式說的是:兩個數的最大公因數,等於「較小的數」和「餘數」的最大公因數。當 b 變成 0 時,gcd(a,0)=a,這就是答案。

🔀 試著補完這張流程圖...

下面的流程圖有些步驟被 ??? 遮住了,試著想想看遮住的地方應該填什麼:

輸入格式: 第一行:正整數 A(1 ≤ A ≤ 10000) 第二行:正整數 B(1 ≤ B ≤ 10000)

輸出格式: 一行,印出 A 和 B 的最大公因數

範例一

輸入輸出
48
18
6

範例二

輸入輸出
100
75
25

範例說明

  1. 第一步:A = 48,B = 18,B ≠ 0,繼續迴圈;48 ÷ 18 = 2 餘 12,所以 A = 18,B = 12
  2. 第二步:A = 18,B = 12,B ≠ 0,繼續迴圈;18 ÷ 12 = 1 餘 6,所以 A = 12,B = 6
  3. 第三步:A = 12,B = 6,B ≠ 0,繼續迴圈;12 ÷ 6 = 2 餘 0,所以 A = 6,B = 0
  4. 第四步:B = 0,迴圈結束,印出 A = 6

老師的提示

輾轉相除法的精髓是同時更新兩個變數:新的 A 是舊的 B,新的 B 是舊的 A 對 B 取餘數。注意更新順序——如果先改了 A,算餘數時就用不到原本的 A 了。


數位根

問題情境:小雯週末在圖書館翻閱一本數學趣味讀物時,看到一個讓她眼睛一亮的神奇數字遊戲:把一個數的各位數字加總,如果結果還是多位數,就再加總一次,一直重複到只剩個位數為止,這個最終結果叫做「數位根」。書上舉的例子讓她印象深刻:9875 先算 9+8+7+5=29,再算 2+9=11,最後 1+1=2,所以 9875 的數位根是 2。小雯覺得這個規則很適合用迴圈來實作,於是決定挑戰看看。請你幫小雯寫程式:輸入正整數 N,輸出它的數位根。

🔍 思考引導

🔀 試著補完這張流程圖...

下面的流程圖有些步驟被 ??? 遮住了,試著想想看遮住的地方應該填什麼:

輸入格式: 第一行:一個正整數 N(1 ≤ N ≤ 1000000)

輸出格式: 一行,印出 N 的數位根(1 到 9 之間的整數)

範例一

輸入輸出
4937

範例二

輸入輸出
98752

範例說明

  1. 第一步:N = 493,位數超過 1 位,進入外層迴圈,開始計算各位數之和
  2. 第二步:493 % 10 = 3,total = 3,N = 49;49 % 10 = 9,total = 12,N = 4;4 % 10 = 4,total = 16,N = 0;內層迴圈結束
  3. 第三步:N = total = 16,位數超過 1 位,再次進入外層迴圈
  4. 第四步:16 % 10 = 6,total = 6,N = 1;1 % 10 = 1,total = 7,N = 0;內層迴圈結束
  5. 第五步:N = total = 7,是個位數,外層迴圈結束,印出 7

老師的提示

while n >= 10: 作為外層條件,每輪用 while n > 0: total += n % 10; n //= 10 計算各位數總和,再令 n = total


完美數判斷

問題情境:阿誠在數學課學到「完美數」這個概念:如果一個正整數恰好等於它所有真因數(除了自身以外的因數)的總和,就叫做完美數。例如 6 的真因數是 1、2、3,而 1+2+3=6,所以 6 是完美數;但 12 的真因數和是 1+2+3+4+6=16≠12,所以 12 不是。阿誠對此非常著迷,他聽老師說歷史上的數學家花了好幾百年才找到少數幾個完美數,而且至今還沒有人知道完美數到底有無限多個還是有限個。他迫不及待想寫一支程式來驗證任意數是否為完美數,請你幫他完成。

🔍 思考引導

💭 如果用數學來表達...

d=1dNN1d=N,則 N 是完美數

其中 dN 表示 d 能整除 N(即 Nmodd=0)。你需要從 1 開始,一路檢查到 N1,把所有能整除 N 的數加起來,最後看總和是否等於 N

🔀 試著補完這張流程圖...

下面的流程圖有些步驟被 ??? 遮住了,試著想想看遮住的地方應該填什麼:

輸入格式: 第一行:一個正整數 N(1 ≤ N ≤ 10000)

輸出格式: 如果 N 是完美數,印出 Yes;否則印出 No

範例一

輸入輸出
6Yes

範例二

輸入輸出
12No

範例說明

  1. 第一步:N = 6,d 從 1 開始,total = 0
  2. 第二步:d = 1,6 % 1 = 0,total = 0 + 1 = 1,d 變成 2
  3. 第三步:d = 2,6 % 2 = 0,total = 1 + 2 = 3,d 變成 3
  4. 第四步:d = 3,6 % 3 = 0,total = 3 + 3 = 6,d 變成 4
  5. 第五步:d = 4,6 % 4 = 2 ≠ 0,跳過,d 變成 5
  6. 第六步:d = 5,6 % 5 = 1 ≠ 0,跳過,d 變成 6
  7. 第七步:d = 6 = N,迴圈結束,比較 total = 6 是否等於 N = 6?是,印出 Yes

老師的提示

whilefor 迴圈從 1 跑到 n-1,累加所有能整除 n 的數。最後比較總和是否等於 n。


到這裡,你已經學會了兩種迴圈:for(我知道要跑幾次)和 while(跑到條件不成立為止)。但你有沒有想過:如果迴圈跑到一半,我突然想「不跑了」或「跳過這一次」呢?

目前你只能等條件自然變成 False 才能離開迴圈。下一節會教你兩個強大的迴圈控制指令,讓你能在迴圈中途「踩煞車」或「按快轉」。

本節小結

🎯 重點回顧:

  • while 條件: 讓電腦重複執行,直到條件變成 False
  • for 適合已知次數,while 適合未知次數
  • while 的三步口訣:初始化 → 條件 → 更新
  • 無窮迴圈:忘記更新條件變數 = 程式永遠跑不完
  • Trace Table 是追蹤迴圈的萬用工具,while 也一樣適用
  • 3N+1 猜想:一個到今天都沒被證明的數學問題,但 while 幾行就能模擬

📝 下一節:「迴圈控制:break 與 continue」:

如果迴圈跑到一半,你找到了想要的東西,不想再跑了,怎麼辦?如果某一輪遇到了不需要處理的情況,想直接跳到下一輪,又怎麼辦?下一節會教你 break(強制離開)和 continue(跳過這一輪),讓你對迴圈有更精細的控制。