和v8干架之pow函数再实现

首先,吹逼可以不用打草稿,能干过v8我还在这个时候写代码?

正题

说明

环境是node,别的系统配置没意义 ,相对比对,实现一个pow函数,然后和v8的比下,顺带试试各种优化性能的江湖传说

第一个实现

function pow(x,e){
    if(e==0)return 1;
    else if(e==1)return x;
    else if(e%2)return pow(x*x,(e-1)/2)*x;
    else  return pow(x*x,e/2); 
};

很眼熟,基本和c里面差不多
然后本着递归不靠谱,先实现一个用栈模拟递归的数组实现

第二个实现

function pow(x,e){
    var i = e;
    var m=[];
    var index =0 ;
    if(e==0)return 1;
    if(e==1)return x;
    while(1){
        //console.log(i);
        if(i==1){
            m.push(x);
            break ;
        }
        else if(i==2){
            m.push(x*x);
            break;
        }
        else{
            if(i%2){
                m.push(x);
                i=(i-1)/2 ;
            }
            else {
                m.push(1);
                i/=2;
            }
        }
    };
    for(i=(m.length-1);i>0;i--)
    {
        m[i-1]=m[i]*m[i]*m[i-1];
    }
    return m[0];
};

代码量一下子上来,然后测试,大概就是给个时间间隔,中间跑很多次函数结果:
native:70,code1:11000;code2:13000
嗯,这是个假数组实现,还不如递归,可见一般情况下,递归还是不错的选择,但是,如果再想下,思考点什么邪术,就可以干一波大事了
首先考虑一下,pow的指数值其实是局限的,或者说大了也没啥卵用,然后呢,这种二分对干的情况,,不由得想起了二进制,的确可以,细节略过,反正就是对比一下数组模拟,来个二进制模拟,这里用了es6的位操作(c里面很常见的套路),然后用了系统计算函数(罪过罪过,说不定就是靠这个函数优化的性能),然后有了下面版本

第三个实现

function pow(x,e){
    var res =x;
    if(e==0)return 1;
    if(e==1)return x;
    if(x==1)return 1;
    var k = 32-Math.clz32(e)-1;
    //console.log('fd'+res);
    for(var i =0 ; i<k;i++)
    {
        if(e&(1<<(k-i-1))){
            res=(res*res*x) ;}
        else {
            res*=res;
        }
    }
    return res ;
};

效果是:native:90,code3:1000
真是飞跃。。。。
接着实验各种邪术江湖传闻,比较靠谱的是:
避免全局查找,将res等变量声明为全局,大概慢两倍或者更多
然后之前数组实现时,将push换为索引,没啥大的改变。
将内部var声明为let,大概也是慢两倍多,安全和效率会有冲突
而使用arguments来直接用实参比用形参访问慢(要计算)
然后有些不靠谱(可能我说的不对):
明确循环终止条件,while比for(;;)好什么的,,没啥用
异步,这个不考虑,没啥用
然后,发现了一个天大的秘密,用几个函数一层层套,居然执行更快了,,,,不过3层左右就可以了,套个9层还是会变慢
然后还有if..eles 比switch ..case好,可能IE会好,不过因此变成了个逼格不错的样子

第四个实现

function pow(x,e){
    var res =x;
    if(e===0)return 1;
    if(e===1)return x;
    if(x===1)return 1;
    //获得e的二进制有效长
    var k = 32-Math.clz32(e)-1;//-1为res有初始赋值
    var i = 0 ;
    for(var  i =0 ; i<k;i++)
    {
        res=e&(1<<(k-i-1))?(res*res*x):(res*res);
    }
    return res ;
};

果然搞个这个条件选择就是感觉不一样了,但其实也没怎么快

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值