C++ Builder 串口控件 | C++ Builder 编程技巧 | C++ Builder 操作指南 | C++ Builder 参考手册 | 基础知识 | cfloat 浮点数 | • 浮点数类型 | • 浮点数异常处理 | • _finite, _finitel | • _isinf, _isinfl | • _isnan, _isnanl | • _fpclass, _fpclassl | • _chgsign, _chgsignl | • _copysign, _copysignl | • _logb, _logbl | • _scalb, _scalbl | • _nextafter, _nextafterl | • _clear87, _clearfp | • _control87, _controlfp | • _status87, _statusfp | • _fpreset | cmath 数学函数 | cstdlib 标准库函数 | System 字符串 | System 日期和时间 | System.Math.hpp 数学函数 | 其他数据类型 | VCL 基础类 | VCL 应用程序 | Pictures 图片 | Graphics 绘图 | Additional 控件 | System 控件 | A ~ Z 字母顺序排列的目录 | 网友留言/技术支持 |
|
victor::_fpclass, victor::_fpclassf, victor::_fpclassl - 获取浮点数值的类型 |
victor::_fpclass, victor::_fpclassf, victor::_fpclassl:获取浮点数值的类型
函数原型:
int _fpclass(double x);
int _fpclass(float x);
int _fpclass(long double x); |
int _fpclassf(float x); |
int _fpclassl(long double x); |
头文件:
#include <cfloat>
命名空间:
victor
自己写的函数,用来代替 <cfloat> 里面有问题的函数 std::_fpclass 和 std::_fpclassl
参数:
x:浮点数
返回值:
值 |
说明 |
_FPCLASS_UNSUP |
不支持的浮点数格式,Unsupported IEEE format。
Win32 定义了这个值,但是经过测试,没发现如何能返回这个值。
Win64 没有定义这个值,并且也不会返回此值。 |
_FPCLASS_SNAN |
Signaling NaN,产生异常的 NAN 值,如果计算出这个结果表明要抛出异常了。
如果计算时产生了异常,是得不到算式的结果的,因为直接跳出了 try { },所以很难得到 Signaling NaN 值。 |
_FPCLASS_QNAN |
Quiet NaN,安静的 NAN 值,无法计算的算式的计算结果。
很容易得到 Quiet NaN:数值 NaN 就是这样的值,函数 std::nan 也可以得到这样的值,0.0 除以 0.0,或者定义域错误,例如给负数开平方 std::sqrt(-1.0) 或取对数 std::log(-2.0) 等得到的值,都是 Quiet NAN。 |
_FPCLASS_NINF |
Negative Infinity,负无穷大,-∞。
负数向上溢出、负数除以 0.0,还有一些函数运算,例如 std::log(0.0) 都会得到负无穷大值。 |
_FPCLASS_NN |
Negative Normal,正常的负数,能够以正常精度表达的负数【注】 |
_FPCLASS_ND |
Negative Denormal,次正常的负数。有效数字向下溢出一部分,可以表达数值,但是无法保证精度了【注】 |
_FPCLASS_NZ |
Negative Zero (-0.0),负零,由负数计算等于零,例如零除以负数,或者负数向下溢出为零。
在判断上,正零和负零认为是相等的,例如 x 等于正零,y 等于负零,if(x==y) 判断为真。 |
_FPCLASS_PZ |
Positive Zero (+0.0),正零,由整数计算等于零,例如零除以正数,或者正数向下溢出为零。
在判断上,正零和负零认为是相等的,例如 x 等于正零,y 等于负零,if(x==y) 判断为真。 |
_FPCLASS_PD |
Positive Denormal,次正常的正数。有效数字向下溢出一部分,可以表达数值,但是无法保证精度了【注】 |
_FPCLASS_PN |
Positive Normal,正常的正数,能够以正常的精度表达的正数【注】 |
_FPCLASS_PINF |
Positive Infinity,正无穷大,+∞。
正数向上溢出、正数除以 0.0,还有一些函数运行,例如 std::pow(0.0,-1.0) 都会得到正无穷大值。 |
函数实现:
//---------------------------------------------------------------------------
namespace victor {
//---------------------------------------------------------------------------
int _fpclass(double x) // Copyright © Victor Chen, http://www.cppfans.com/
{
unsigned long long ullBinary = *(unsigned long long *) &x; // 1,11,52
int bNegative = (ullBinary & 0x8000000000000000ull) != 0; // 符号位:0正,1负
if((ullBinary & 0x7FFFFFFFFFFFFFFFull) == 0) // 零值:除了符号位之外其他位都等于零
return bNegative ? _FPCLASS_NZ : _FPCLASS_PZ; // 负数 ? 负零 : 正零
if((ullBinary & 0x7FF0000000000000ull) == 0) // 指数等于零为零或丢失精度的浮点数
return bNegative ? _FPCLASS_ND : _FPCLASS_PD;
if((ullBinary & 0x7FF0000000000000ull) == 0x7FF0000000000000ull) // 指数全一 NAN 或 INF
{
if((ullBinary & 0x000FFFFFFFFFFFFFull) == 0) // 尾数等于零为 INF
return bNegative ? _FPCLASS_NINF : _FPCLASS_PINF;
else // 尾数不等于零,尾数的符号位区分安静 NAN 和异常 NAN
return (ullBinary & 0x0008000000000000ull) ? _FPCLASS_QNAN : _FPCLASS_SNAN;
}
return bNegative ? _FPCLASS_NN : _FPCLASS_PN; // 特殊值处理完了,剩下的就是普通的值
}
//---------------------------------------------------------------------------
int _fpclassf(float x) // Copyright © Victor Chen, http://www.cppfans.com/
{
unsigned long ulBinary = *(unsigned long *) &x; // 1,8,23
int bNegative = (ulBinary & 0x80000000ul) != 0; // 符号位:0正,1负
if((ulBinary & 0x7FFFFFFFul) == 0) // 零值:除了符号位之外其他位都等于零
return bNegative ? _FPCLASS_NZ : _FPCLASS_PZ; // 负数 ? 负零 : 正零
if((ulBinary & 0x7F800000ul) == 0) // 指数等于零为零或丢失精度的浮点数
return bNegative ? _FPCLASS_ND : _FPCLASS_PD;
if((ulBinary & 0x7F800000ul) == 0x7F800000ul) // 指数全一 NAN 或 INF
{
if((ulBinary & 0x007FFFFFul) == 0) // 尾数等于零为 INF
return bNegative ? _FPCLASS_NINF : _FPCLASS_PINF;
else // 尾数不等于零,尾数的符号位区分安静 NAN 和异常 NAN
return (ulBinary & 0x00400000ul) ? _FPCLASS_QNAN : _FPCLASS_SNAN;
}
return bNegative ? _FPCLASS_NN : _FPCLASS_PN; // 特殊值处理完了,剩下的就是普通的值
}
//---------------------------------------------------------------------------
int _fpclassl(long double x) // Copyright © Victor Chen, http://www.cppfans.com/
{
#if defined(_M_IX86)
unsigned char *pBinary = (unsigned char *)&x; // 10 个字节的 80-bit double 值,x86 架构为小端存储
unsigned long long ullSignificand = 0x7FFFFFFFFFFFFFFFull & *(unsigned long long *)(pBinary); // 尾数
unsigned long ulExponent = 0x7FFF8000ul & *(unsigned long *)(pBinary+6); // 指数
int bNegative = (0x80 & *(pBinary+9)) != 0; // 是否为负数。符号位:0正,1负
if((ullSignificand==0) && (ulExponent==0)) // 零值:尾数和指数都等于零
return bNegative ? _FPCLASS_NZ : _FPCLASS_PZ; // 负数 ? 负零 : 正零
if(ulExponent == 0) // 指数等于零:丢失精度的数值
return bNegative ? _FPCLASS_ND : _FPCLASS_PD; // 负数 ? 丢失精度的负数 : 丢失精度的正数
if(ulExponent == 0x7FFF8000ul) // 指数全一 NAN 或 INF
{
if(ullSignificand == 0) // 尾数等于零为无穷大
return bNegative ? _FPCLASS_NINF : _FPCLASS_PINF; // 负数 ? 负无穷大 : 正无穷大
else // 尾数不等于零,尾数的符号位区分安静 NAN 和异常 NAN
return (ullSignificand & 0x4000000000000000ull) ? _FPCLASS_QNAN : _FPCLASS_SNAN;
}
return bNegative ? _FPCLASS_NN : _FPCLASS_PN; // 特殊值处理完了,剩下的就是普通的值
#else
return _fpclass((double)x); // 64-bit double
#endif
}
//---------------------------------------------------------------------------
int _fpclass(float x) // Copyright © Victor Chen, http://www.cppfans.com/
{
return _fpclassf(x); // 32-bit float
}
//---------------------------------------------------------------------------
int _fpclass(long double x) // Copyright © Victor Chen, http://www.cppfans.com/
{
#if defined(_M_IX86)
return _fpclassl(x); // 80-bit long double
#else
return _fpclass((double)x); // 64-bit long double
#endif
}
//---------------------------------------------------------------------------
} // namespace victor
//--------------------------------------------------------------------------- |
例子:
函数 std::_fpclass 的例子
把 std::_fpclass 换成 victor::_fpclass 就可以了
兼容性:
函数 \ C++ Builder 编译器 |
bcc32 |
clang32 |
clang64 |
victor::_fpclass |
√ |
√ |
√ |
victor::_fpclassf |
√ |
√ |
√ |
victor::_fpclassl |
√ |
√ |
√ |
相关链接:
• _finite • _isinf • _isnan • _fpclass • _control87 • SetExceptionMask • _matherr • 浮点数异常处理
|
|
|
|