← 所有文章

工程數值的四捨五入 負數邊界與顯示格式

· 站長

分開原值、取整值與畫面格式,用正負中點及固定小數演算法避免取整規則混用。

先說清楚你要改顯示 還是改數值

畫面把12.35顯示為12.4,不代表PLC中的值已經變成12.4。如果下一段仍用原值做比較,操作員看到的數字和比較結果就可能不同。先把原始值、供控制使用的值、顯示字串分開,再決定哪一層需要取整。這篇用正負中點說明不同策略,最後給一個固定小數的可復算方法。

本文的合成資料原本以0.01單位的整數保存,例如1235表示12.35。要求輸出改成0.1單位,並採「最近值,中點遠離零」。這是我們明訂的應用規則,不等於所有ROUND函式的保證。若使用PLC內建函式,必須選定平台與版本,依其官方定義及目標測試核對。

層次 例子 是否改變運算值
原始資料 Raw100=1235 代表12.35 保留原始解析度
已取整數值 Rounded10=124 代表12.4 是,已丟掉0.01位
顯示字串 畫面顯示12.4 可能只改外觀
比較門檻 採原值或取整值 必須在規格寫明

正負中點最能暴露取整規則

保留一位小數時,1.25位於1.2和1.3正中間。「中點遠離零」給1.3;「中點取偶數」給1.2,因為保留位最後一碼2為偶數。−1.25的對稱結果則分別是−1.3與−1.2。不要只寫「四捨五入」就假設所有同事理解同一個中點策略。

原值 向零截斷到0.1 中點遠離零 最近且中點取偶數
1.24 1.2 1.2 1.2
1.25 1.2 1.3 1.2
1.35 1.3 1.4 1.4
−1.24 −1.2 −1.2 −1.2
−1.25 −1.2 −1.3 −1.2
−1.35 −1.3 −1.4 −1.4

上表是十進位數學規則的比較,不是任何PLC實測畫面。當資料本身是二進位浮點,顯示的1.25附近值可能是計算後近似值;你應記錄完整來源、運算步驟與型別。若要測「剛好中點」,不要拿只在畫面上看似1.25的任意計算值代替。

CODESYS的REAL_TO_INT文件有取整說明,而TRUNC_INT明確取整數部分;這已足以說明轉換方式並非同義。本文不使用未查證的通用ROUND語法,而用明訂的整數單位演算法,讓每個中點都能精確驗算。

用整數單位實作明確的中點策略

假設Raw100位於−100000~100000,採至少32位有號中間變數。先計算絕對值a,除10得到商q與餘數r;當r≥5就把q加1,最後恢復原始正負號。結果Rounded10的單位是0.1,不能再當成原來0.01的數字使用。

教學偽碼,非特定PLC可編譯語法:
先拒絕超出 ±100000 的 Raw100
a := ABS(寬型別的 Raw100)
q := a DIV 10;r := a MOD 10
若 r >= 5,q := q + 1
Raw100 < 0 時 Rounded10 := -q,否則 Rounded10 := q
Valid := TRUE
Raw100 a q/r Rounded10 工程解讀
1234 1234 123/4 123 12.3
1235 1235 123/5 124 12.4
−1235 1235 123/5 −124 −12.4
5 5 0/5 1 0.1
−5 5 0/5 −1 −0.1
0 0 0/0 0 0.0

先限範圍再取絕對值,是為了避開最小負整數的ABS溢位。若Raw100使用完整32位範圍,−2147483648的正值不在同型別內,不能直接取ABS。這個例子用明確範圍保證中間運算可容納;變更量程時,這項檢查必須一起重做。

浮點邊界與雙重取整怎麼驗收

若來源是REAL,乘100再轉成整數的那一步也有取整,可能改變你真正想測的值。以數學上的1.249為例,直接取到一位小數是1.2;先取兩位得1.25,再取一位可能變1.3。這叫雙重取整,不能把它誤認為同一項操作的精度升級。

資料流程 數學預期 風險
1.249直接取一位 1.2 依原值最近值
1.249先兩位再一位 1.25再1.3 多一次取整改變結果
原值12.349只顯示一位 畫面12.3 原值仍12.349 比較邏輯仍可能用原值
原值12.349真正取一位 運算值12.3 原始資訊若未另存便丟失
  1. 先固定要驗收的規則與單位,明列是否允許雙重取整。

  2. 準備正負中點、中點兩側、零、上下界,以及資料無效案例。

  3. 在目標PLC記錄原始儲存值、型別、每段中間值與結果,不能只抄HMI顯示。

  4. 核對官方函式定義與實際結果;不一致時先查二進位表示、型別轉換與編譯器設定。

  5. 保存版本及測試輸入,之後換CPU或函式庫時用相同資料重跑。

用門檻比較看出顯示與運算的差別

假設判定條件是原始值大於十二點三五,現在來源是十二點三四九。畫面若只顯示一位小數,操作員看到十二點三,條件仍然不成立。若先取一位再比較,送進比較器的也變成十二點三,但這是另一條運算路徑。兩者在這一筆剛好相同,不足以證明整個設計等價。

再用十二點三五一測試。直接用原始值比較時條件成立;若先取一位得到十二點四,再用十二點三五比較也成立。接著把門檻改成十二點三八,原值比較不成立,取整值比較卻成立。這個例子告訴你,控制門檻不能由畫面的顯示位數偷偷決定,應明寫比較採用哪個欄位。

建立驗收時,請把這兩欄同時顯示:未取整原值,以及真正提供下游使用的取整結果。畫面文字只用來幫助閱讀,不作為測試唯一證據。若畫面自行取整而資料記錄保留更多位數,兩邊應標明精度;否則維護人員可能把正常的顯示差異誤判為通訊資料不一致。

本篇固定小數演算法之所以先限定範圍,是要讓取絕對值、商加一與符號還原都能放在中間型別內。不要刪掉範圍限制後仍宣稱演算法適用全部整數。需求擴大時,從最小負值開始重新檢查每一步,尤其有號最小值的正數通常無法由同位寬有號型別表示。

若欄位原本已是百分之一單位的整數,不要先轉成浮點再乘回一百,增加不必要的轉換。直接用商與餘數能保留精確的十進位中點。反過來,如果來源本來是浮點,就不能無條件把乘一百轉整數視為無損,必須先規定轉換過程允許的誤差與取整方式。

練習時可把正負一千二百三十四、一千二百三十五與一千二百三十六依序送入,確認中點兩側和中點本身的結果。再測零與正負五,觀察符號是否對稱。最後把輸入設在允許範圍之外,確認程式拒絕資料且不把前一次結果標成新值;這樣才算驗收了成功與失敗兩條路徑。

完成結果 失敗排查與限制

本例完成後,Raw100=1235輸出124,−1235輸出−124;正負5分別輸出1與−1,且原始Raw100仍保留。若只改畫面格式,Rounded10不應被誤宣稱已更新。遇到差一個最末位,先找是哪一步取整,不要直接加入0.0001把某幾筆數字推到想要的一側。

問:負數四捨五入就是減0.5嗎?必須連同後續截斷方向一起定義,不能單獨套常數。問:多留一位再取整一定較好嗎?雙重取整可能改變最終結果,應從需要的原始精度直接套規則。問:改成LREAL就一定完全正確嗎?它增加精度,但不會讓所有十進位小數都可精確表示。

適用型號與限制:公式為本文自訂固定小數教學設計,輸入範圍±100000且使用至少32位有號中間值。具體官方參照為CODESYS線上轉換文件,Q06UDVCPU的ABS、除法、餘數及型別指令要另核對。

參考:CODESYS REAL LREAL 轉換與取整定義

參考:CODESYS TRUNC_INT 負數向零截斷

延伸閱讀


使用 PLC 工具箱 →