LeetCode-50:关于浮点型数字求高次幂的高效运算

题目描述比较简单,就是求-100.0到100.0的n次幂,n为32位有符号整数。

比如求2.00000的10次幂,则需要返回的值为1024.00000;诶,1024刚过:(

  • 首先比较无脑的就是一次次的去累积乘,乘n次,思维很清晰,想法很危险。
  • 32位有符号整数,[﹣231,231﹣1],即[﹣2147483648,2147483647]这个范围,我没有试过这种方法,但是看评论有人说这个会报超时。20多亿次乘积运算,有点伤。
  • 然后就是大家比较认可的二分递归运算,思路也很清晰,将n一份为二,一直分到n=1或者﹣1。
    代码示例:
    public double myPow2(double x, int n) {
        if (n == 0) { return 1; }
        if (n == 1) { return x; }
        if (n == -1) { return 1 / x; }
        double half = myPow(x, n / 2);
        double rest = myPow(x, n % 2);
        double total = rest * half * half;
        return total;
    }
  • 其实在二分递归之前,我想到的是将n拆成一个个2的n次幂的和,即xn=xn1+n2+n3+n4+…=xn1*xn2*xn3xn4……,比如10次方,10=2+8,就可计算x的2次方和8次方,再将两个结果乘起来。当然你可能会觉得计算2次方和8次方的过程有重复运算,其实想象成2进制右移运算,或者/2运算的话,可以避免这个重复。
    先看下面的代码:
    public double myPow(double x, int n) {
        long num = n;
        if (num < 0) {
            x = 1 / x;
            num = -num;
        }
        //最后需要返回的结果,过程中需要累积乘多个x的n1、n2、n3……次幂
        double result = 1;
        //记录当前位代表的幂级值
        double currentMagnification = x;
        for (long i = num; i > 0; i >>= 1) {
            if ((i % 2) == 1) {
                result = result * currentMagnification;
            }
            currentMagnification = currentMagnification * currentMagnification;
        }
        return result;
    }

为了更方便理解,以上面计算2的10次幂为栗子说明一下。
10的2进制表示为1010,前面省略了28个0。
第0次循环:i=10,即1010,result=1,currentMagnification=21=2;
第一次循环,i=5,即0101,result=1,currentMagnification=22=4;
第二次循环,i=2,即0010,result=14=4,currentMagnification=24=16;
第三次循环,i=1,即0001,result=4,currentMagnification=28=256;
第四次循环,i=0,即0000,result=4
256=1024,currentMagnification=216=65536;
循环结束。
这里其实还有一个需要特别注意的地方:long num = n;
这一句并非可有可无,如果省略将n转换为long类型这样一个过程,那么当n=Integer.MIN_VALUE = -2147483648 时,程序运行结果会有异常。2147483648并不是int类型,已经超过了这个范围了。
int num= ﹣(﹣2147483648) = ﹣2147483648
或者
int num = Math.abs(﹣2147483648)= ﹣2147483648

发布了92 篇原创文章 · 获赞 13 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_41885819/article/details/102737302