先說清楚你要改顯示 還是改數值
畫面把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 | 原始資訊若未另存便丟失 |
先固定要驗收的規則與單位,明列是否允許雙重取整。
準備正負中點、中點兩側、零、上下界,以及資料無效案例。
在目標PLC記錄原始儲存值、型別、每段中間值與結果,不能只抄HMI顯示。
核對官方函式定義與實際結果;不一致時先查二進位表示、型別轉換與編譯器設定。
保存版本及測試輸入,之後換CPU或函式庫時用相同資料重跑。
用門檻比較看出顯示與運算的差別
假設判定條件是原始值大於十二點三五,現在來源是十二點三四九。畫面若只顯示一位小數,操作員看到十二點三,條件仍然不成立。若先取一位再比較,送進比較器的也變成十二點三,但這是另一條運算路徑。兩者在這一筆剛好相同,不足以證明整個設計等價。
再用十二點三五一測試。直接用原始值比較時條件成立;若先取一位得到十二點四,再用十二點三五比較也成立。接著把門檻改成十二點三八,原值比較不成立,取整值比較卻成立。這個例子告訴你,控制門檻不能由畫面的顯示位數偷偷決定,應明寫比較採用哪個欄位。
建立驗收時,請把這兩欄同時顯示:未取整原值,以及真正提供下游使用的取整結果。畫面文字只用來幫助閱讀,不作為測試唯一證據。若畫面自行取整而資料記錄保留更多位數,兩邊應標明精度;否則維護人員可能把正常的顯示差異誤判為通訊資料不一致。
本篇固定小數演算法之所以先限定範圍,是要讓取絕對值、商加一與符號還原都能放在中間型別內。不要刪掉範圍限制後仍宣稱演算法適用全部整數。需求擴大時,從最小負值開始重新檢查每一步,尤其有號最小值的正數通常無法由同位寬有號型別表示。
若欄位原本已是百分之一單位的整數,不要先轉成浮點再乘回一百,增加不必要的轉換。直接用商與餘數能保留精確的十進位中點。反過來,如果來源本來是浮點,就不能無條件把乘一百轉整數視為無損,必須先規定轉換過程允許的誤差與取整方式。
練習時可把正負一千二百三十四、一千二百三十五與一千二百三十六依序送入,確認中點兩側和中點本身的結果。再測零與正負五,觀察符號是否對稱。最後把輸入設在允許範圍之外,確認程式拒絕資料且不把前一次結果標成新值;這樣才算驗收了成功與失敗兩條路徑。
完成結果 失敗排查與限制
本例完成後,Raw100=1235輸出124,−1235輸出−124;正負5分別輸出1與−1,且原始Raw100仍保留。若只改畫面格式,Rounded10不應被誤宣稱已更新。遇到差一個最末位,先找是哪一步取整,不要直接加入0.0001把某幾筆數字推到想要的一側。
問:負數四捨五入就是減0.5嗎?必須連同後續截斷方向一起定義,不能單獨套常數。問:多留一位再取整一定較好嗎?雙重取整可能改變最終結果,應從需要的原始精度直接套規則。問:改成LREAL就一定完全正確嗎?它增加精度,但不會讓所有十進位小數都可精確表示。
適用型號與限制:公式為本文自訂固定小數教學設計,輸入範圍±100000且使用至少32位有號中間值。具體官方參照為CODESYS線上轉換文件,Q06UDVCPU的ABS、除法、餘數及型別指令要另核對。