29. Divide Two Integers

思路:这道题让我们求两数相除,而且规定我们不能用乘法,除法和取余操作,那么我们还可以用另一神器 位操作Bit Operation,思路是,如果被除数大于或等于除数,则进行如下循环,定义变量t等于除数,定义计数p,当t的两倍小于等于被除数时,进行如下循环,t扩大一倍,p扩大一倍,然后更新res和m。这道题的OJ给的一些test case非常的讨厌,因为输入的都是int型,比如被除数是-2147483648,在int范围内,当除数是-1时,结果就超出了int范围,需要返回INT_MAX,所以对于这种情况我们就在开始用if判定,将其和除数为0的情况放一起判定,返回INT_MAX。然后我们还要根据被除数和除数的正负来确定返回值的正负,这里我们采用长整型long来完成所有的计算,最后返回值乘以符号即可。
用到的知识:左移1位,相当于乘2,右移1位,相当除以2。
第一次提交

int divide(int dividend, int divisor)
{
    int INTMAX = 2147483647;
    int INTMIN = -2147483648;
    if(divisor == 0)
    {
        return INTMAX;
    }
    if(dividend == INTMIN && divisor == -1)
    {
        return INTMAX;
    }
    if(dividend == divisor)
    {
        return 1;
    }
    long long divid = abs((long long)dividend);  //第17行
    long long divis = abs((long long)divisor);
    long res = 0;
    //做符号判断  //判断两个数符号是否相同,可使用按位异或
    int sign = ((dividend < 0) ^ (divisor < 0)) ? -1 : 1;  //同号sign=1,异号sign=0
    if((divisor == 1) || (divisor == -1))
    {
        return sign == 1 ? divid : -divid;
    }
    //做除法
    while(divid > divis)
    {
        long long t = divis ,p =1;
        while(divid >= (t << 1))  //左移1位等价于乘2
        {
            t = t << 1;
            p = p << 1;
        }
        res = res + p;
        divid = divid - t;
    }
    return sign == 1 ? res : -res;
}

LeEtcode报错

Line 17: Char 23: runtime error: negation of -2147483648 cannot be represented in type 'int'; cast to an unsigned type to negate this value to itself (solution.c)

abs的返回值overflow,同时我在本地的编译器提示我应该使用llabs()函数,abs()函数和llabs()函数的区别如下

int abs( int n );
long labs( long n );
long long llabs( long long n );
__int64 _abs64( __int64 n );

也就是abs()函数的返回值是int类型,当abs()函数的输入为INT_MIN时,abs()函数将直接返回INT_MIN,这一点在微软官网上给出了解释。
29. Divide Two Integers
我在Qt中做了一个实验

int main()
{
    printf("%d",abs(INT_MIN));
    return 0;
}

运行结果如下:
29. Divide Two Integers

第二次提交

int divide(int dividend, int divisor)
{
    int INTMAX = 2147483647;
    int INTMIN = -2147483648;
    if(divisor == 0)
    {
        return INTMAX;
    }
    if(dividend == INTMIN && divisor == -1)
    {
        return INTMAX;
    }
    if(dividend == divisor)
    {
        return 1;
    }
    long long divid = llabs((long long)dividend);
    long long divis = llabs((long long)divisor);
    long res = 0;
    //做符号判断  //判断两个数符号是否相同,可使用按位异或
    int sign = ((dividend < 0) ^ (divisor < 0)) ? -1 : 1;  //同号sign=1,异号sign=0
    if((divisor == 1) || (divisor == -1))
    {
        return sign == 1 ? divid : -divid;
    }
    //做除法
    while(divid > divis)
    {
        long long t = divis ,p =1;
        while(divid >= (t << 1))  //左移1位等价于乘2
        {
            t = t << 1;
            p = p << 1;
        }
        res = res + p;
        divid = divid - t;
    }
    return sign == 1 ? res : -res;
}

参考资料:
1 abs,labs,llabs函数的说明 https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/abs-labs-llabs-abs64?view=vs-2017
2 https://www.cnblogs.com/grandyang/p/4431949.html