C++学习------cmath头文件的源码学习03
原创
©著作权归作者所有:来自51CTO博客作者桑榆晚见天的原创作品,请联系作者获取转载授权,否则将追究法律责任
宏函数定义---分类函数
isnan--判断数据是否是一个number
还是之前的例子,判断是否是一个合法的实数:
printf ("isnan(0.0) : %d\n",isnan(0.0));
printf ("isnan(1.0/0.0) : %d\n",isnan(1.0/0.0));
printf ("isnan(-1.0/0.0) : %d\n",isnan(-1.0/0.0));
printf ("isnan(sqrt(-1.0)): %d\n",isnan(sqrt(-1.0)));
//测试结果
isnan(0.0) : 0
isnan(1.0/0.0) : 0
isnan(-1.0/0.0) : 0
isnan(sqrt(-1.0)): 1
我们来看看函数实现:
28 int __isnanf(float x)
29 {
30 int32_t ix;
31 GET_FLOAT_WORD(ix,x);
32 ix &= 0x7fffffff;
33 ix = 0x7f800000 - ix;
34 return (int)(((uint32_t)(ix))>>31);
35 }
有了前面的经验,我们可以很直接得看出,先截取指数域与小数域,ix = 0x7f800000 - ix,得到指数域差值和负的小数域,转换成uint32_t是为了右移运算时左边补0,此时右移31位,实际上是为了检测符号位,也即是前面相减的过程是否溢出得到了负数,即在指数域为11111111时,小数域还有数据,就会导致减出负数,最后判断时符号位为1,判断为NAN,这个也是IEEE754的规定:指数域11111111,小数域有数据表示非法;小数域无数据表示无穷,根据符号位确定是正无穷还是负无穷。
isnormal---判断数据是否是一个非0正常数(非0正常浮点数)
直接来看代码,实际上调用了fpclassify接口,判断返回值是否是FP_NORMAL,实现逻辑也比较简单:
999 /* Return nonzero value if X is neither zero, subnormal, Inf, nor NaN. */
1000 # if (__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__) \
1001 || __glibc_clang_prereq (2,8)
1002 # define isnormal(x) __builtin_isnormal (x)
1003 # else
1004 # define isnormal(x) (fpclassify (x) == FP_NORMAL)
1005 # endif
signbit---返回输入数x的符号是否是负号
看一下之前的例子,一个非0数的符号为负时返回true,其余情况返回false:
printf ("signbit(0.0) : %d\n",signbit(0.0));
printf ("signbit(1.0/0.0) : %d\n",signbit(1.0/0.0));
printf ("signbit(-1.0/0.0) : %d\n",signbit(-1.0/0.0));
printf ("signbit(sqrt(-1.0)): %d\n",signbit(sqrt(-1.0)));
//测试结果signbit(0.0) : 0
signbit(1.0/0.0) : 0
signbit(-1.0/0.0) : 1
signbit(sqrt(-1.0): 1
复制代码
看下代码实现: 这里需要我们了解一下GCC内建函数的知识 # GCC种builtin函数的介绍以及实现过程 我们来看看GCC代码中的定义模块:mirrors.tuna.tsinghua.edu.cn/help/gcc.gi…
再往下就涉及到具体的机器架构对应的内建实现了,我们就不深入说明了。