【FLOOR函数的标量实现】

cmath


一、FLOOR简介

floor函数,其功能是“向下取整”,或者说“向下舍入”、“向零取舍”,即取不大于x的最大整数,与“四舍五入”不同,下取整是直接取按照数轴上最接近要求值的左边值,即不大于要求值的最大的那个整数值。

二、算法

1.标量源码

#include "math.h"
#include "math_private.h"
static const float huge = 1.0e30;
float
floorf(float x)
{
        int32_t i0,j0;
        u_int32_t i;
        GET_FLOAT_WORD(i0,x);
        j0 = ((i0>>23)&0xff)-0x7f;
        if(j0<23) {
            if(j0<0) {  /* raise inexact if x != 0 */
                if(huge+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */
                    if(i0>=0) {i0=0;}
                    else if((i0&0x7fffffff)!=0)
                        { i0=0xbf800000;}
                }
            } else {
                i = (0x007fffff)>>j0;
                if((i0&i)==0) return x; /* x is integral */
                if(huge+x>(float)0.0) { /* raise inexact flag */
                    if(i0<0) i0 += (0x00800000)>>j0;
                    i0 &= (~i);
                }
            }
        } else {
            if(j0==0x80) return x+x;    /* inf or NaN */
            else return x;              /* x is integral */
        }
        SET_FLOAT_WORD(x,i0);
        return x;
}

代码解读(大致实现原理):

首先我们需要对传入的浮点数x做一个取阶码exp运算,这里需要了解IEEE754浮点数标准,即第一位符号位,接8位指数位,接23位尾数位,那么取阶码就是右移23位后,和0xff做一个&运算,再减掉偏置值就可以得到真值j0了。
然后对真值进行范围判断,先看最简单的两种情况,x在(0,1)区间内都返回0;在(-1,0)区间内返回-1。此时j0 是小于0的。
然后在j0在(0,23)内时,做一个对0x007fffff右移j0位的运算,这里之前我不太明白,发现这个数字是符号位和指数位全为0,尾数位全为1。如果x是整数(integer),那么0x007fffff右移j0位后,再与x的浮点数形式做&运算,结果必然是0(这里要知道前面符号位和指数位肯定是0,因为你和0做的&),那也就是说尾数位全0,为什么?因为整数啊,如果移完后尾数不为0那么结果肯定就不为0,那说明小数点后有非零数存在那就不是整数了。
在x<0时,x先加一下对0x00800000右移j0位后的结果,再与~i(就是尾数全0,符号位和指数位全1)做&运算。这个自己可以举个例子就搞明白了,比如-1.5,即为1011 1111 1100 0000 0000……
加完后得到1100 0000 0100 0000 0000…… 再和~i做个&运算,得到1100 0000 0100 0000……就是-2,没问题。
NAN和INF比较容易看出,真值为128那说明指数位全1了,返回x本身就行。

向量化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值