← 所有文章

FIELD NOTES / PLC 程式與控制

浮點NaN與Inf在控制前如何攔截

PLC 程式與控制作者:站長預估 6 分鐘閱讀

以明示端序和IEEE binary32位元例,建立finite、quality、range三道控制前閘門,分離來源無效與運算溢位。

本文目錄

先確認位元格式與端序

浮點資料看起來是數字,不代表它可以拿去比較或控制。NaN表示不是數值,正負Inf表示無限大;它們可能來自來源欄位無效,也可能由運算溢位產生。控制前要先建立有限性和品質檢查,不能等到輸出動作後才從畫面猜原因。

以下用IEEE 754 binary32作資料格式示例,並明示以十六進位表示32位元編碼:0x7FC00000是常見的quiet NaN、0x7F800000是+Inf、0xFF800000是−Inf、0x3F800000是1.0。這些是格式示例,不是某一款PLC的裝置位址、暫存器或API。

解析前先定義端序與封包排列。若四個位元組在網路訊息中是大端順序,應先依規格重組成32位元,再解讀符號、指數與分數欄;若直接把小端資料當大端,正常1.0也會被讀成另一個值。端序不明時,狀態應是來源格式未知,不應硬猜成有限數。

除浮點位元外,還要保留來源文字、封包、品質旗標與轉換錯誤。來源是"NaN"、空字串或截斷封包時,與在支援非陷阱IEEE浮點運算環境中除以零而得到的Inf不是同一個原因;其他平台可能直接報錯,不能假設一定產生Inf。原因分離後,維修人員才能分別追查輸入清洗、感測器、資料傳輸或算式溢位。

位元驗證也要涵蓋符號位、指數全一與分數欄位,而不是只比對一個文字標籤。不同NaN payload仍屬NaN類別;若診斷需要區分payload,應額外保存原始32位元。解析器不能因某個NaN樣式未列在範例中,就誤判為一般有限數。

同一閘門在啟動、穩態與恢復都要一致。恢復good資料前先重新驗證,不以重啟後第一筆值自動清除失敗告警;告警解除也要留下時間、來源與原因於完整紀錄表中。

finite先行 再查品質與工程範圍

建議控制閘門順序是:先確認格式已成功解碼,再判斷數值finite,接著判斷來源quality,最後檢查工程range。只有三者都通過才建立usable=true的候選值。NaN不等於0,也不應在檢查失敗時用零取代;失敗結果應保留原值或位元證據並標記不可用。

NaN與自身比較不相等,和有限數的有序大小比較也不成立。常見錯誤是只在「x小於下限或x大於上限」時拒絕;NaN讓兩個條件都為假,程式反而放行。正向要求「x大於等於下限且x小於等於上限」會拒絕NaN,但仍建議先明確分類有限性,才能區分原因;比較鏈不是通用PLC語法。

以工程範圍0到100為例,x=50且quality=good才可通過;x=−1或x=101是finite但range失敗;x=NaN或±Inf是finite失敗。quality=bad即使數字落在0到100也不能放行,因為數值外觀不能證明來源可信。這三個狀態要在紀錄中分開。

檢查結果最好採不可變的快照:記下讀取時間、來源序號、解碼後分類與規格版本。控制迴路若讀到另一個週期的值,可能把上一筆good品質誤配到本筆NaN。每次更新都要連同品質與有限性一起交換,不能只更新一個浮點欄位。

range門檻的閉區間或開區間要寫清楚。若允許端點,檢查是0≤x且x≤100;若不允許端點,則是0<x且x<100。此處只是數學表示,實際程式應使用目標平台已驗證的型別和比較方法,不把Python函式名稱或本文的狀態名稱冒充PLC指令。

分開來源無效與運算溢位

假設輸入封包直接帶來0x7FC00000,先記錄decoded=NaN、source_status=invalid_value,控制閘門拒絕。另一案例是兩個有限值相乘後超過binary32可表示範圍;在相應的非陷阱模式及捨入設定下可能產生+Inf,其他平台可能報錯;這筆應記為operation_overflow。兩者都不能控制,但處置方向不同,前者查來源,後者查算式、單位或上限。

若結果是−Inf,除了finite失敗,也要保留運算方向與相關輸入的品質。不要把正負Inf夾到最大工程值後繼續,因為夾限可能掩蓋倍率錯誤。若規格允許飽和,必須另有明確狀態、事件和人工審查,不可把它當作一般有效值。

正常案例可列1.0的編碼0x3F800000、quality=good、範圍0到2,最後usable=true;失敗案例列NaN、+Inf、−Inf、有限但超界、有限且範圍內但quality=bad。每筆都回報原始編碼或來源文字、finite結果、quality結果、range結果與最終原因。

控制前最後一步應只消費usable=true且仍屬同一時間戳與資料世代的值。資料在檢查後才更新,期間若來源跳代、超時或品質改變,要讓候選失效。本文描述資料閘門與應用案例,沒有假稱任何PLC平台已提供相同的浮點例外、暫存器或診斷位。

來源也可能直接傳來Inf,運算也可能產生NaN;不能只憑特殊值種類就指定根因。只有保留運算前輸入、來源封包及平台例外證據,才能把原因確定為來源無效或運算溢位。證據不足時標原因待查,避免讓維修人員沿錯誤方向排查。

測試邊界並明確記錄限制

驗收表至少包含四個指定位元模式、正常有限值、兩側工程邊界、超界值、來源品質失敗、格式錯誤、運算溢位與逾時。預期結果要同時寫finite、quality、range和usable,避免只看最後輸出是否為零。每個失敗案例還要核對原因沒有被後續步驟覆蓋。

若系統只收到十六進位字串,先定義大小寫、前綴、長度與端序;不接受含糊輸入。若系統收到文字NaN或Inf,需由資料契約決定是否允許這些標記,允許也只能進入無效狀態,不能因文字解析成功就當成可控制數字。

控制器的實際浮點格式、例外模式、比較指令、通訊字組交換和診斷行為都必須查目標手冊。離線用Python或NumPy核對位元與數學概念,只能支持資料設計;不能據此宣稱Q系列PLC已完成編譯、模擬或現場測試。

限制也要寫入交付文件:有限性檢查不會修復錯誤來源,quality旗標的意義取決於來源協定,工程range取決於製程,端序取決於介面。只要其中一項未定義,最安全的資料狀態是不可用並要求補齊規格,而不是用預設值讓控制繼續。

觀測與控制也要分層:診斷畫面可以顯示原始位元和原因,控制輸出只接受通過閘門的快照。保留失敗證據有助於查找偶發問題,但不應把診斷值誤接到動作命令。

常見問題

問:NaN可以當零避免控制中斷嗎?答:不可以;NaN代表值無效,轉成零會把來源問題隱藏並可能觸發錯誤動作。

問:上下限比較會不會攔下NaN?答:正向要求兩個範圍條件同時成立會拒絕NaN;只檢查超界後取反則可能誤放行。先做有限性分類,再檢查品質和範圍,原因最清楚。

問:+Inf和來源NaN可以共用一個錯誤嗎?答:控制上都要拒絕,但來源無效與運算溢位應分開記錄,排查方向不同。

問:0x7FC00000在每個平台都一定是唯一NaN嗎?答:它是本文的binary32 quiet NaN特定例;位元格式、端序與平台解讀仍須依介面和目標手冊確認。

參考:IEEE官方標準頁面,作為binary32、特殊值與浮點格式的規格來源;本文四個位元模式是教學案例,非PLC暫存器定義。

參考:Python math官方文件的isfinite說明,用於離線數學概念核對;本文不將Python函式當成PLC API。

延伸閱讀