為什麼加密公式是 'A' + ((ch - 'A' + key) % 26),而直接 (ch + key) % 26 是錯的?'A' 起什麼作用?
| 字符 | ASCII 十進制 | 字母表索引 (0-25) |
|---|---|---|
| 'A' | 65 | 0 |
| 'B' | 66 | 1 |
| ... | ... | ... |
| 'Z' | 90 | 25 |
關鍵認知:字母 'A'-'Z' 在 ASCII 中**不連續對應 1-26**,而是 **65-90**。直接對 ASCII 值運算會破壞字母循環邏輯。
index = ch - 'A' ('A'→0, 'B'→1 ... 'Z'→25)newIndex = (index + key) % 26 (處理正負 key,確保在 0-25)encryptedChar = 'A' + newIndex (0→'A', 1→'B' ... 25→'Z')'A' + ((ch - 'A' + key) % 26)假設 ch = 'B' (66), key = 2:
'A' + ((66 - 65 + 2) % 26) = 65 + 3 = 68 = 'D' ✅(66 + 2) % 26 = 68 % 26 = 16 → 非字母字符 ❌錯誤公式將 ASCII 值直接模 26,結果落在 0-25 範圍,完全脫離字母 ASCII 區間 (65-90)。
int effectiveKey = key % 26;
if (effectiveKey < 0) effectiveKey += 26; // 統一轉為正向位移
// 或統一公式:
int newIndex = (ch - 'A' + key % 26 + 26) % 26; // 雙重 +26 保證非負
char result = 'A' + newIndex;
public String caesarCipher(String text, int key) {
key = key % 26;
if (key < 0) key += 26;
StringBuilder sb = new StringBuilder();
for (char ch : text.toCharArray()) {
if (Character.isUpperCase(ch)) {
sb.append((char) ('A' + (ch - 'A' + key) % 26));
} else if (Character.isLowerCase(ch)) {
sb.append((char) ('a' + (ch - 'a' + key) % 26));
} else {
sb.append(ch); // 非字母保持不變
}
}
return sb.toString();
}
'A' (65) 是 **ASCII 字母區塊的基址**。加密本質是:**字符 → 字母索引 (0-25) → 位移循環 → 索引 → 字符**。減去 'A' 完成「字符→索引」,加上 'A' 完成「索引→字符」,中間模 26 實現循環。跳過基址轉換直接操作 ASCII 值,破壞了字母連續性假設,導致結果錯誤。