zoukankan      html  css  js  c++  java
  • Leetcode: Pow(x, n) and Summary: 负数补码总结

    Implement pow(x, n).

    Analysis:  Time Complexity: O(LogN)

    Iterative code: refer to https://discuss.leetcode.com/topic/40546/iterative-log-n-solution-with-clear-explanation

    N = 9 = 2^3 + 2^0 = 1001 in binary. Then:

    x^9 = x^(2^3) * x^(2^0)

    We can see that every time we encounter a 1 in the binary representation of N, we need to multiply the answer with x^(2^i) where i is the ith bit of the exponent. Thus, we can keep a running total of repeatedly squaring x - (x, x^2, x^4, x^8, etc) and multiply it by the answer when we see a 1.

     1 public class Solution {
     2     public double MyPow(double x, int n) {
     3         double ans = 1;
     4         long absN = Math.Abs((long)n);
     5         while(absN > 0) {
     6             if((absN&1)==1) ans *= x;
     7             absN >>= 1;
     8             x *= x;
     9         }
    10         return n < 0 ?  1/ans : ans;
    11     }
    12 }

    Recursive code:

     1 double pow(double x, int n) {
     2     if (n == 0) return 1.0;
     3     double half = pow(x, n/2);
     4     if (n%2 == 0)
     5     {
     6         return half*half;
     7     }
     8     else if (n>0)
     9     {
    10         return half*half*x;
    11     }
    12     else
    13     {
    14         return half/x*half;
    15     }
    16 }

    这道题其实细细玩味起来有不少值得注意的地方:位运算的细节。

    我第一遍代码里面其实有不妥的地方,比如第4行的1/helper(x, -n),当n取Integer.MIN_VALUE时,取反结果还是自己

    JAVA中整数采用符号二进制补码表示(Two's Complement),补码对正数没什么好说的,但对负数还是要注意。

    比如:

    -8  1000    -4  1100    0  0000    4  0100

    -7  1001    -3  1101    1  0001    5  0101

    -6  1010    -2  1110    2  0010    6  0110

    -5  1011    -1  1111    3  0011    7  0111

    一旦某一端overflow, 就会跑到另外一端去wrap up,这就是为什么Integer.MAX_VALUE+1 会是Integer.MIN_VALUE

    Integer.MIN_VALUE,即-2147483648,二进制位如下: 

    1000 0000 0000 0000 0000 0000 0000 0000 

     

    在计算机的运算中,“-”(前缀)运算表示各二制位取反再加1,也就是说 b = -a 在计算机内部是 b = ~a + 1 这样处理的,所以上面的位就变成了: 

     

       1000 0000 0000 0000 0000 0000 0000 0000 Integer.MIN_VALUE 

    取反 0111 1111 1111 1111 1111 1111 1111 1111 (取反之后变成了Integer.MAX_VALUE) 

    加1 1000 0000 0000 0000 0000 0000 0000 0000 -Integer.MIN_VALUE(与原来的结果一样)

    这就导致了我如下的一段code stackoverflow了

     1 public class Solution {
     2     public double pow(double x, int n) {
     3         if (n < 0) return 1/pow(x, Math.abs(n));
     4         if (n == 0) return 1.0;
     5         else {
     6             double half = pow(x, n/2);
     7             if (n % 2 == 0) return half * half;
     8             else return half * half * x;
     9         }
    10     }
    11 }

    java.lang.StackOverflowError     last input: 1.00000, -2147483648, 因为-2147483648取反永远是自己,好像0取反永远是自己一样。我第一遍的code也只是侥幸结果对,其实并不好。还是像第二遍code那样写比较好

  • 相关阅读:
    番外篇 之 JS调用
    C# 匿名方法及Lambda表达式
    番外篇 之 C#委托
    番外篇之多线程
    23----2013.07.01---Div和Span区别,Css常用属性,选择器,使用css的方式,脱离文档流,div+css布局,盒子模型,框架,js基本介绍
    22----2013.06.29---HTML--html介绍.超链接和图片,表格,表单,表单标签,meta,复习当天内容
    AccessHelper类
    WPF视频教程系列笔记
    《深入浅出WPF》 学习笔记
    基于MAVEN构建Spring MVC初始化配置
  • 原文地址:https://www.cnblogs.com/EdwardLiu/p/3982752.html
Copyright © 2011-2022 走看看