前幾天,我確認了不同人代墊、指定參與者與自訂分攤。今天把這些結果放在一起,理解最後的付款清單是怎麼產生的。每筆支出都有付款人和分攤者,但如果逐筆還錢,很容易出現你付我、我又付你的情況。
淨額抵銷先不急著安排每一筆轉帳,而是整理每個人的已代墊與應分攤,再用「已代墊減掉應分攤」算出差額。正數代表應收回,負數代表還需要付出,零則表示這個人已經平衡。
最容易理解的例子是,小明先替小美付了 100 元,小美又替小明付了 40 元。如果逐筆還款,需要往返兩次;放在一起計算後,小美只要付小明 60 元,就能得到相同的最終結果。原本的兩筆支出仍然保留,抵銷的是最後需要交付的差額。
另一個例子是三人循環代墊:小明替小美付 100 元,小美替阿哲付 100 元,阿哲又替小明付 100 元。每個人已付與應負擔都是 100 元,淨額全部為零,因此不需要真的繞一圈付款。今天的計算測試也確認,這種情況會得到空的轉帳清單。
回到原本的聚會範例,晚餐、咖啡和車資合計 1,830 元。小明的淨額是正 543 元,小美是負 377 元,阿哲是負 166 元,因此最後只要小美付小明 377 元,阿哲付小明 166 元。清單上的交付金額合計是 543 元,不需要等於消費總額 1,830 元,因為其中一部分已經在代墊時支付了。
檢查現有程式後,可以看到它先把需要收款和付款的人分開,分別依差額大小排列,再逐一配對。每次交付的金額,取目前付款人尚欠金額與收款人尚需金額之中較小的數字。完成其中一人的差額後,就繼續處理下一位。
這個做法也支援一個人付給多個人。例如小明應收 200 元、小美應收 100 元、阿哲應付 300 元,就會由阿哲分別付給兩人。系統不是硬性找出唯一的收款人,而是依整份帳的淨額安排清單。
今天驗證時,我不只檢查清單看起來是否合理,也模擬照清單交付。付款人的負差額加上付出的金額,收款人的正差額扣掉收到的金額,最後每個人都應該歸零。同時檢查金額為正整數、沒有自己付給自己,以及所有付款對象都在成員名單裡。
也核對了代墊合計與分攤合計都等於消費總額,淨額合計為零,而付款清單的合計等於所有正淨額的加總。這些條件能幫助發現重複付款、漏掉某位成員,或金額多算少算的問題。
瀏覽器部分,先確認原本的三筆聚會清單,再把三筆支出都改為 300 元、全部由三人平均分攤,付款人各自保留為小明、小美和阿哲。此時總額是 900 元,每人代墊 300 元,也負擔 300 元,畫面顯示零筆轉帳與「大家剛剛好,不需要再轉帳」。
接著把小明代墊的晚餐改成 600 元。總額變成 1,200 元,每人應分攤 400 元,小明已付 600 元,另外兩人各付 300 元,因此清單重新出現小美與阿哲各付小明 100 元的兩筆付款。這確認了系統不會因為之前已平衡,就一直保留舊狀態。
不過,結算金額正確,不代表轉帳筆數一定最少。今天特別加入一個六人的案例:三位收款人分別應收 10、8、2 元,三位付款人分別應付 8、7、5 元。現有方法會產生五筆付款,而且按照清單交付後,所有差額確實都能歸零。
但同一個案例也可以用四筆完成:應付 8 元的人直接付給應收 8 元的人;應付 7 元的人付給應收 10 元的人;應付 5 元的人再分別付剩下的 3 元和 2 元。這組替代清單也通過歸零檢查,證明現有方法並不保證每次都找到最少筆數。
因此,今天沒有把這個結果描述成計算錯誤,也沒有把功能升級成尚未完成的最佳化演算法。目前的完成範圍是產生能正確結清淨額的清單,並如實說明筆數限制。未來如果要保證最少筆數,需要另外設計與驗證求解方式。
今天共執行九項計算案例,全部通過,包含聚會範例、雙向互欠、循環互欠、全員平衡、平衡後修改、一人付給多位、空帳本、一元零頭,以及上述筆數反例。瀏覽器則完成原始清單、全員平衡及修改後重新結算三個檢查點。
這些測試仍然是選定情境,不能代表所有組合與裝置都已驗證。付款清單也只是計算建議,沒有執行銀行轉帳,更不代表使用者已經付款。現金面額、找零與資料保存,仍依後續安排處理。
第十四天沒有修改產品程式,也沒有提交或發布新版,而是把結算邏輯和限制確認得更清楚。這次讓我學到,和 AI 合作時,除了要求正確答案,也要檢查它對答案的描述是否超出證據。「可以結清」和「一定最少筆」是不同的承諾。
下一天會做第一次完整流程檢查,從一場聚餐的成員、支出與修改,一路核對到最後結算,整理前半段已完成的成果與還需要補上的地方。