← 所有文章

FIELD NOTES / 資料記錄與報表

報表四捨五入與原始總量不一致如何解釋

資料記錄與報表作者:站長預估 5 分鐘閱讀

用具體十進位算例分清逐筆與總計捨入,核對型別、模式與可追溯的顯示差額。

本文目錄

先確認總計是在哪一步捨入

報表三列相加與總計差零點零一,未必是漏資料,也可能是每列先四捨五入與全部加總後才四捨五入的差異。先查原始精度、計算順序與捨入模式,再決定是否為錯誤;不要為了讓畫面合起來好看,直接改掉某筆原始量測。

把原始保存值、運算值與顯示值分開。原始值保存系統取得的資料與精度,運算值按規定單位和型別計算,顯示值才套用小數位格式。顯示兩位小數不表示原始資料只有兩位,也不表示後續匯出應只保留兩位。

本文適用於重量、能耗與產量報表等一般數值呈現,捨入政策必須依契約與用途訂定。金額、法定計量或檢驗判定可能另有規定,不能直接拿本文教學模式替代。PLC或儀表已量化的原始值,也不能靠增加顯示位數提高量測精度。

先寫清楚三件事:保留幾位、遇到恰好一半時如何處理,以及在每筆、每組或最終總計哪一層處理。不同軟體預設不一定相同,「大家都用round」不代表結果一致;型別與函式版本都需要核對。

用三筆零點三三五算出差異

假設三筆十進位重量均為0.335公斤,採最接近值、恰好一半時遠離零的捨入方式,顯示到小數第二位。每筆顯示0.34,三個顯示值相加為1.02;原始總和則為1.005,最後捨入得到1.01,兩者差0.01。

兩個總計分別回答「已捨入列值的和」與「原始值總和的顯示」。報表若要求總計採原始值計算,就顯示1.01並註明各列為捨入顯示;若契約要求每筆先量化再合計,則依該規則得到1.02,不能事後混用另一種計法。

這個例子必須以精確十進位數理解。如果程式先用二進位浮點數保存0.335,實際內部值可能不恰等於十進位0.335,臨界捨入結果可能不同。要驗證十進位政策,使用適合的十進位型別或可控的整數倍率模型。

另一種常見方式是恰好一半時取偶數末位。精確1.005取兩位時,取偶模式得到1.00,前述遠離零模式得到1.01。這不是誰算術比較差,而是規則不同;將模式名稱與幾個臨界例子寫進介面需求最清楚。

完成後應能同時列出原始三筆、每筆顯示、原始總和、最終顯示及差額來源。若同一規則重算仍無法解釋差異,再查漏筆、重複、單位與轉換,不要把所有小差異一律歸因於四捨五入。

選擇型別並避免重複捨入

Python Decimal可明確指定捨入模式;建立精確十進位測試值時,從十進位字串建立,避免先轉成二進位浮點再交給Decimal而帶入原本誤差。這是離線核對方法,不代表PLC內建了相同型別或模式。

PostgreSQL的numeric適合精確十進位運算,real與double precision屬不精確型別。官方文件也指出numeric與浮點型別在中間值捨入上可能不同。跨資料庫、試算表與程式語言交換結果時,不要只核對小數位數而忽略型別。

整數倍率模型可把0.335公斤保存為335公克,再將三筆加成1005公克,最後依顯示規則轉為公斤。倍率、單位與整數容量必須固定;大量累加前檢查是否溢位,並確認來源真的只需要這個解析度。

避免中途多次捨入。例如先把每秒值捨入,再算分鐘平均,再捨入後算小時平均,會累積量化影響,還可能混入不等樣本數問題。若需求允許,保留足夠精度的總和與有效數,到指定輸出層才捨入,並記錄計算順序。

負數也要測。精確負1.25取一位,恰好一半遠離零得到負1.3,取偶得到負1.2;不能把「五入」簡化為永遠往正方向加。截斷、向下取整與最接近值捨入是不同運算,尤其負數結果差異很明顯。

讓報表可讀也能回查

報表註記可直接寫「明細顯示至小數第二位,總計由未捨入數值計算」。匯出另保留原始精度欄或詳細查詢入口,讓需要核對的人能重算。只給已捨入的明細卻要求對方重現原始總計,資訊本來就不足。

若業務要求明細顯示和必須等於指定總計,需要另訂差額分配規則,保存分配前值、調整量與依據。調整顯示或分攤結果應與原始量測分開,不能把最後一列默默加零點零一,讓後續分析誤以為設備真的量到那個值。

失敗時先用少量已知十進位值重算,查每一層是否轉型或捨入,再比對原始事件集合與單位。若差額隨筆數增長,可能是逐筆捨入累積;若差了一千倍,優先查公斤與公克,不要用捨入理由掩蓋倍率錯誤。

驗收包含正負數、零、恰好一半、稍低於一半、稍高於一半與大量累加。比較時使用明訂的數值或顯示規則,不隨意設定一個很大的容差讓測試通過;真正的量測不確定度與純數值捨入誤差也應分別說明。

百分比也有相同問題。三個等量分類各占三分之一,顯示一位小數時各為百分之三十三點三,相加只有百分之九十九點九,並不表示漏了一類。若要分配顯示尾差,規則與調整對象要公開。累積表計則先以完整精度的期末減期初,再按政策顯示;不要先捨入兩個讀數再相減,否則微小期間用量可能被量化成零。

練習與常見問題

練習:三筆均為精確0.144,顯示兩位且採最接近值捨入。每筆0.14,顯示值合計0.42;原始總和0.432,最後顯示0.43。請在報表上標明總計採哪個順序,並保留原始值供核對。

問:總計比明細相加多一分位就一定錯嗎?答:先查計算順序與捨入模式,再核對資料完整性。

問:改成更多小數位就能提高感測器精度嗎?答:不能,只是顯示更多數字。

問:用Decimal就一定不必管理精度嗎?答:仍須設定足夠運算精度、明確模式與正確輸入來源。

問:可以自動修改最後一列來湊總計嗎?答:只有明訂且可追溯的分配規則才可使用,原始量測仍須保留。

參考:Python decimal:十進位型別、quantize與捨入模式。

參考:PostgreSQL 18 Numeric Types:numeric與浮點型別的精度及捨入特性。

延伸閱讀