C和C++11標准提供了類似於isnan、isfinite、isinf、isnormal、fpclassify分別用於判斷是非數(NaN)值、有限制、無窮值、正常數值等。
今天在使用Modbus讀取設備對應寄存器的float狀態值時,出現一些問題,導致數據不能正常獲取,最后發現原來設備對應的寄存器里面會出現一些無效的值,導致讀取顯示出錯,沒做容錯判斷處理。后面加上條件判斷就可以了。
bool D02011C01::getState()
{
bool rc = false;
Modbus::RTU rtu;
// 獲取工況參數(共12項)
Uint8Array req = rtu.req(deviceId(), 4, 1110, 24);
if (SendCmd(rtu, req, 3000, 3))
{
float xishu[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
for (int i = 0; i < 12; i++)
{
float val;
// 獲取的val值可能不是有效的float類型,比如說:-1.#IND,需要對所獲取的結果做有效性判斷
if (rtu.get_value(val, 2 * i, false, false) && !std::isnan(val))
{
setStateData(i + 1, val);
rc = true;
}
}
}
return rc;
}
注意
對於float類型的值,C和C++11中都做了相應的處理,用於判斷一個float值是否為無窮大、非數( NaN )值;
有多個擁有不同符號位和載荷的不同 NaN 值,參閱 std::nan 及 std::numeric_limits::quiet_NaN 。
NaN 值決不與自身或其他 NaN 值比較相等。 IEEE-754 不要求復制 NaN 保留其位表示(符號與載荷),盡管大多數實現保留。
另一種測試浮點值是否 NaN 的方式是與自身比較: bool is_nan(double x) { return x != x; }
示例如下:
#include <iostream>
#include <cmath>
#include <cfloat>
int main()
{
std::cout << std::boolalpha
<< "isnan(NaN) = " << std::isnan(NAN) << '\n'
<< "isnan(Inf) = " << std::isnan(INFINITY) << '\n'
<< "isnan(0.0) = " << std::isnan(0.0) << '\n'
<< "isnan(DBL_MIN/2.0) = " << std::isnan(DBL_MIN/2.0) << '\n'
<< "isnan(0.0 / 0.0) = " << std::isnan(0.0/0.0) << '\n'
<< "isnan(Inf - Inf) = " << std::isnan(INFINITY - INFINITY) << '\n';
}
輸出:
isnan(NaN) = true
isnan(Inf) = false
isnan(0.0) = false
isnan(DBL_MIN/2.0) = false
isnan(0.0 / 0.0) = true
isnan(Inf - Inf) = true
有時候發現不少函數以前沒怎么用過,遇到問題才發現又學到了一些知識。
C和C++11標准提供了類似於isnan、isfinite、isinf、isnormal、fpclassify分別用於判斷是非數(NaN)值、有限制、無窮值、正常數值等。
isnan
NAN
Not-A-Number (constant )
isfinite
Is finite value (macro )
isinf
Is infinity (macro/function )
isnormal
Is normal (macro/function )
fpclassify
Classify floating-point value (macro/function )
參考資料:
1、https://zh.cppreference.com/w/cpp/numeric/math/isnan
2、https://en.cppreference.com/w/cpp/numeric/math/isnan
3、http://www.cplusplus.com/reference/cmath/isnan/