一 先分辨變更量 相對百分比與百分點
百分比變更率要先寫清楚分母。當 old>0,本篇採 change_percent=(new-old)/old×100。100 變成 120 是 +20%,100 變成 80 是 -20%。這個數字描述相對於前值的比例,不是差值本身;同一筆資料還應保存 delta=new-old,避免使用者把 +20% 與 20 個單位混在一起。
old=0 時傳統公式沒有定義。0 變成 10 的 delta 是 +10,但百分比變更率不能自動寫 0%、100% 或 infinity。0 變成 0 同樣沒有傳統百分比分母,雖然 delta=0 且可標記 NoChange。系統應輸出明確狀態,例如 BaselineZero,並將 delta、old、new 與規則版本一併留存。
百分點用在兩個比例或比率的差值。20% 變成 25% 是 +5 percentage points;若以原比例作相對變更,則是 (25-20)/20×100=+25%。兩者回答不同問題,欄位名稱不可只叫 change。顯示介面應分開呈現 delta_units、relative_percent 與 percentage_points。
| old | new | delta | 相對變更率 | 狀態 |
|---|---|---|---|---|
| 100 | 120 | +20 | +20% | Defined |
| 100 | 80 | -20 | -20% | Defined |
| 0 | 10 | +10 | 未定義 | BaselineZero |
| 0 | 0 | 0 | 未定義 | NoChange/BaselineZero |
| 20% | 25% | +5個百分點 | +25% | 兩種指標並列 |
計算前應把欄位狀態分成 HasBaseline、Defined、Undefined 與 Rejected,而不是只用一個布林值。old=0、new=10 是有前值且 delta 有定義,但 relative_percent 未定義;沒有前值則連 delta 的變更語義也不成立。這個區分可避免介面把「零基準」誤畫成通訊故障。
第一個有效值沒有可比較的前值時,也應使用 BaselineMissing,而不是拿 0 當基準。缺少前值時delta也未定義;報表可另顯示目前new值,但delta與變更率均維持未建立狀態。這樣下游不會把尚未建立基準誤認為製程沒有變動。
二 負前值與方向解讀
當 old<0,傳統公式仍可計算,但方向直覺可能改變。例:old=-10、new=-5,delta=+5,代入 (−5−(−10))/−10×100 得 -50%。數學上結果是 -50%,但實際數值向零移動;若操作員把負號解讀成下降,就會得到錯誤結論。報表要同時顯示 delta 的符號與分母正負。
若需求是保留數值增減方向、以舊值幅度作尺度,可以另定signed_normalized_percent=delta/abs(old)×100。它不是幅度本身的相對變更;幅度變更需另算(abs(new)-abs(old))/abs(old)。上述例子會得到 +50%,但這是另一個明確命名的指標,不能把它偷偷取代傳統公式。old=-10、new=-15 時 delta=-5,abs 分母指標為 -50%,表示距離零點增加而數值更負。兩種規則都要在資料契約中固定。
對溫度、壓差、偏差量等可能為負的資料,先問清楚工程意義:是比較有號數值,還是比較幅度、能量或距離?若單位或量測零點改變,跨版本直接算百分比也可能失真。應保存 unit、scale、calibration_version 與 baseline_source,拒絕把不同定義硬接成一條曲線。
| 案例 | old→new | delta | 傳統公式 | 可選幅度指標 |
|---|---|---|---|---|
| 偏差A | -10→-5 | +5 | -50% | +50% |
| 偏差B | -10→-15 | -5 | +50% | -50% |
| 電流 | 4→6 A | +2 A | +50% | 同值 |
| 不同版本 | 10→12,scale改變 | +2 | 需先換同單位 | 不可直接比較 |
負值還要考慮零點校正造成的符號翻轉。若同一設備先以 -0.2 bar 讀值,校正後變成 +0.1 bar,傳統百分比會被小負分母放大;報表應先比對校正版本與物理零點,再決定是否只呈現 delta 與跨零事件。跨零可另標 CrossingZero,不用單一百分號承擔方向解釋。
驗收時把負值案例放進測試矩陣,明確確認顯示欄位的名稱與符號。不要用「百分比必須向上就是正」這類口號修正結果;應回到公式、分母與指標語義,並讓操作員能看到原始 old、new、delta。
百分比需要有意義的比例尺度。攝氏溫度零點是約定,10°C到20°C不能直接宣稱物理溫度加倍;即使算出100%,也不代表適合的工程指標。溫度可先報差幾°C,需要絕對溫度比值時再用適當的絕對尺度。
三 極小基準 單位與版本
即使 old 不等於零,極小基準也會放大噪聲。假設 old=0.01、new=0.02,公式給 +100%;若感測器解析度是 0.01,這可能只是由一個量化階跳到下一階,不能直接當重大製程變化。規格可設定 baseline_floor,例如 abs(old)<0.05 時只輸出 delta 並標 SmallBaseline,但門檻要由工程需求決定,不能把 0.05 當通用標準。
單位換算要在計算前完成。若 old 是 1000 mL、new 是 1.2 L,先轉成相同單位後 delta=200 mL、相對變更 +20%;若把數字直接代入,會得到 -99.88% 的錯誤結果。資料欄位需帶 unit,並拒絕將版本不同的縮放係數當成同一量測。
保留 raw_old、raw_new、工程值、conversion_version 與計算時間。當校正係數從 v1 改為 v2,歷史資料可選擇重算,但重算結果要標明 derived_version,不覆蓋原始快照。若前值來自另一批次或另一設備,狀態應是 BaselineMismatch,而不是正常變更率。
| 情況 | old | new | 處理 | 狀態 |
|---|---|---|---|---|
| 極小基準 | 0.01 | 0.02 | 可算delta,依門檻停用相對率 | SmallBaseline |
| 同單位 | 1000mL | 1200mL | 先換同單位 | Defined +20% |
| 不同單位 | 1000mL | 1.2L | 轉成1200mL | Defined +20% |
| 校正版本變更 | v1值10 | v2值12 | 先核對conversion_version | BaselineMismatch/重算 |
| 缺前值 | 無 | 10 | 保存10作基準 | BaselineMissing |
門檻不應只寫一個數字而沒有單位。對流量可用 0.1 L/min,對有號偏差量可用0.05工程單位;若資料由整數縮放而來,門檻應在轉換後工程單位判斷。當 old=0.04、new=0.06 且門檻為 0.05 時,delta=0.02 可保存,但相對率應標 SmallBaseline;當 old=0.06 才按定義計算。
顯示格式化只在最後一步做。計算時保留足夠精度,避免先把 0.0199 顯示成 0.02 再拿顯示值計算。若 PLC 使用整數縮放,先以整數 raw 計算差值或轉成明確工程型別;不要假定不同控制器的 REAL、LREAL 或除法捨入方式相同。
四 零分母排查與批次驗收
實作流程可分五步:讀取 old/new 與品質;確認兩筆單位和版本一致;計算 delta;本例有號分母版本在old非零且abs(old)不低於門檻時計算relative_percent;old為負時另標NegativeBaseline。正分母限定的報表則應拒絕負基準,不能與本例混用。任何一步失敗都保留原始資料,不能以 0、100 或 infinity 填補。
假設 本例 在 09:00 讀到 old=100,09:05 讀到 new=120,應記錄 delta=20、relative_percent=20%、status=Defined。另一組獨立案例仍以old=100為基準、new=80,才是delta=−20、relative_percent=−20%;若順接120→80,結果應為−33.333…%。若 09:10 讀到 old=0、new=10,輸出 delta=10、relative_percent 未定義、status=BaselineZero;操作畫面可顯示「需建立基準」。
排查一筆異常時先核對 raw 與單位,再看 baseline_source、conversion_version 和時間排序。若看到 infinity,通常是零分母未攔截;若看到 100%,可能是程式把 old=0→new>0 強制視為滿幅變化;若負值方向讓人困惑,檢查是否把 abs 分母指標誤標成傳統百分比。
| 測試案例 | 輸入 | 預期 delta | relative_percent | reason |
|---|---|---|---|---|
| 正常上升 | 100→120 | 20 | 20% | Defined |
| 正常下降 | 100→80 | -20 | -20% | Defined |
| 零到十 | 0→10 | 10 | 未定義 | BaselineZero |
| 零到零 | 0→0 | 0 | 未定義 | NoChange/BaselineZero |
| 負前值 | -10→-5 | 5 | -50% | NegativeBaseline |
| 小基準 | 0.01→0.02 | 0.01 | 依門檻停用 | SmallBaseline |
驗收時還要測試順序錯亂與重複樣本。09:05 的 new 先到、09:00 的 old 後到,不能把兩者直接當正常前後值;應以 timestamp 或 sequence 判定 OutOfOrder。相同 sequence 重送則只保留一次。這些狀態與零分母狀態不同,分開記錄才能知道是公式問題、資料時間問題,還是來源重送。
若要將結果送往 HMI 或歷史資料庫,建議同時寫入 calculation_rule、baseline_status、delta、relative_percent、unit 與 source_timestamp。relative_percent 未定義時不要寫空白後讓資料庫自動轉零,而應寫 NULL 並以 status 解釋原因。報表排序也要依 timestamp 或 sequence,而不是依完成寫入順序,避免重連後晚到的資料把前值關係倒置。
五 驗收 FAQ 與來源
本題的驗收基準是:100→120 得 +20%,100→80 得 -20%,0→10 只得 delta +10 且變更率未定義,0→0 仍未定義,20%→25% 同時顯示 +5 個百分點與相對 +25%。負前值 -10→-5 使用傳統公式得到 -50%,如採有號差除舊值幅度的指標則另列+50%,不可混名。
完成測試後,將計算結果與 reason 一起寫入稽核紀錄,並以固定的公式版本供報表重現。算例與流程已核對;實際資料型別、時間戳與持久化仍需在選定平台驗證。
FAQ1:old=0、new=10 能否顯示 +100%?答:不能。傳統分母為零,應顯示 delta=+10 與 BaselineZero;是否另定百分比必須建立明確業務指標。
FAQ2:20% 變 25% 是 +5% 還是 +25%?答:差值是 +5 個百分點;以 20% 為分母的相對變更是 +25%。兩欄應分開命名。
FAQ3:負前值 -10 變 -5 為何是 -50%?答:依傳統有號分母公式,delta=+5、分母=-10,所以是 -50%。若要表達有號值增減,可另列delta/abs(old)的+50%;真正幅度由10減到5則是−50%,三者不可混名。
FAQ4:極小 old 可以照算嗎?答:數學上可算,但結果可能被量化噪聲放大。應依資料契約設 baseline_floor,停用或標記 SmallBaseline,保留 delta 與原始資料。
參考:Python math 官方文件:浮點、有限值與數值運算參考,非控制器資料型別保證。