Reverse Integer - Leetcode

26 篇文章 0 订阅

题目补充要求:如果输入的int很大,经过逆转之后会有越界的可能。
例如:x = 1147483648,result = 8463847411,结果明显越界了,因此在这里我们需要对是否越界进行一个判断,如果越界则return 0。int表示数的范围是[-2147483648,2147483648)。
相关知识:见博文 计算机编码与变量范围
本题思路简单,但要注意判断是正是负。

class Solution {
public:
    int reverse(int x) {
       long long k=0;
       long long y=0;//这里之所以要定义一个long long型的,是因为在x=-2147483648时,取正会越界。
       bool flag=x>0?true:false;
       if(flag==false)
            y=-x;
       else y=x;
       int i=10;
       while(y!=0)
       {
           k=k*10+y%i;
           y=y/i;
       }
       if(k>2147483647||(flag==false && k >2147483648)) return 0;  //判断是否越界
       if(flag==false) return (int)(-k);
       else return (int)k;
    }
};

(我觉得代码没问题啊,为什么不能通过。。)经过昨天笔者查看资料外加问大神同学,最后明白一二,现在总结一下问题以及改进办法。
1.在mian()函数中定义x=-2147483648(也就是-2^31),报错:C4146 一元负运算符应用于无符号类型,结果仍为无符号类型 。
虽然x是在int的表示范围内。由于编译器收到的源代码都是字符串形式的,-2147483648对于编译器是字面量,编译器看不懂字面量,需要将字面量转化成具体数值,因此编译器在翻译 “int x = -2147483648;” 这句源代码的时候,编译器的处理过程是这样的:
a. 提取 - 号
b.提取数字部分先翻译成一个正整数 temp
c. 将 - 号应用到 正整数 上,构成最后的结果

unsigned int temp=2147483648; //b步(因为提取出的数值部分2^31超过int的表示范围,所以编译器用unsigned int 来存储)
temp=-temp;  //c步 (因为是用无符号数来存储数值的,所以对无符号数取负是错误的,因此会报错,报错发生在这一步)
int n = temp;  //c步

因此在mian()中定义 x=-2147483647-1或者-2147483646-2或者0x80000000就不会报错。
2.在x=-2147483648时,为什么y=-2147483648?
因为-2^31是一个比较特殊的数字,当你对它进行取负的时候(补码符号位不变,其余各位取反,最后加1),最后还是它本身。等于这个程序最后的K的符号还是和x一样,所以在判断是否越界时出现问题。将k >2147483648改成k<-2147483648,就可以AC。

第二种解决方式:
这里是先将x逐位分离,再改变正负号。长整数用16进制表示更为清晰直观。

int reverse(int x) {
    int num[32];
    for (int i = 0; i < 32; i++)
        num[i] = 0;
    bool positive = x > 0 ? true : false;
    int j = 0;
    while (x != 0)
    {
        int digit = x % 10;
        num[j++] = positive ? digit : -digit;
        x = x / 10;
    }
    long long result = 0;
    int m = 0;
    while (m < j)
    {
        result = result * 10 + num[m++];
    }
    if (positive == false && result>0x80000000) return 0;
    else if (positive&&result > 0x7fffffff) return 0;
    return positive ? result : -result;
}

补充:0x80000000=-2^31,0x80000001=-2^31+1(仍在范围之类,并不是表示越界的数。0x80000000一直+1就是将数字变大(因为是负数))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值