整数取反(取负)运算

整数取反(取负)运算

参考文章: https://www.cnblogs.com/xiaodingmu/p/8215613.html

基础知识

整数在计算机中以补码形式存储,由如下一些注意点:
(1)其中正数的补码、源码、反码都相同;
  例: 5的补码为10000000 00000000 00000000 00000110
(2)负数的补码=原码除符号位外取反+1;
  例:-5的补码为10000000 00000000 00000000 00000110
(3)数在计算中以补码形式存放,且数的运算通过补码进行;

取反运算

32为的int类型,
1.对于正数5
5的原码、反码、补码均为:00000000 00000000 00000000 00000101

2.对于负数5
因为负数的反码为对该数的原码除符号位外各位取反,补码为其反码加1,所以对于-5:
原码为:10000000 00000000 00000000 00000101
反码为:11111111 11111111 11111111 11111010
补码为:11111111 11111111 11111111 11111011

3.int的最小值为-2147483648,按照计算方法,
原码:10000000 00000000 00000000 00000000
反码:11111111 11111111 11111111 11111111
补码:00000000 00000000 00000000 00000000

+0的原码、补码、反码均为00000000 00000000 00000000 00000000
如果计算机中,-2147483648用补码00000000 00000000 00000000 00000000来表示则和0的补码一样,不能区分开;
故而计算机中,-2147483648用补码10000000 00000000 00000000 00000000来表示。
32位最小负整数的补码为10000000 00000000 00000000 00000000

计算机中-2147483648取反为:01111111 11111111 11111111 11111111,此为存储正数的补码,换算原码得到数为2147483647
单目运算符“-”为取负,-2147483648取负为2147483648,显然超过int类型范围(-2147483648~2147483647),刚好超过一个就变为-2147483648,所以其对应的补码仍为10000000 00000000 00000000 00000000,

(1) 对应补码理解就是-x=~x+1;即补码取反加1,10000000 00000000 00000000 00000000取反加1后任然为10000000 00000000 00000000 00000000,对应数为-2147483648
(2) 1-i为(-i)+1,对应补码为:
10000000 00000000 00000000 00000000+00000000 00000000 00000000 00000001=10000000 00000000 00000000 00000001
转换为十进制为:- 2147483647
(3) -1-i为(-i)+(-1),对应补码为:
10000000 00000000 00000000 00000000+11111111 11111111 11111111 11111111=01111111 11111111 11111111 11111111
转换为十进制为: 2147483647
其实也可以从十进制理解:-2147483648-1=-2147483649,超过范围后变为2147483647


实验代码

int main()
{
    int val = INT_MIN; // -2147483648
    cout << "val      = " << val <<endl;
    cout << "~val     = " << ~val <<endl;
    cout << "-val     = " << -val <<endl;
    cout << "1-val    = " << 1-val <<endl;
    cout << "-1-val   = " << -1-val <<endl;
    cout << "abs(val) = " << abs(val) << endl;
    return 0;
}

运行结果

val      = -2147483648
~val     = 2147483647
-val     = -2147483648
1-val    = -2147483647
-1-val   = 2147483647
abs(val) = -2147483648

绝对值计算

实验1: -2147483648

如果要对int类型的数计算绝对值,需要注意下边界条件,对于-2147483648,使用abs函数得到的还是-2147483648。
需要扩展位数才能得到正数,在32位环境中,int和long都是4字节,需要使用long long int 或者unsigned int
实验代码

int val = INT_MIN; // -2147483648
    cout << "val = " << val <<endl;
    cout << sizeof(long) << endl;
    cout << sizeof(int) << endl;
    cout << abs((long long)val) << endl;
    cout << -(long long)val << endl << endl;

    //-2147483648取反+1,即0x01111111 11111111 11111111 11111111 + 1 = 0x10000000 00000000 00000000 00000000,表示2147483648
    cout << -(unsigned int)val << endl;
    //-2147483648的补码直接将符号位看做数值,0x10000000 00000000 00000000 00000000,表示2147483648
    cout << (unsigned int)val << endl;
    cout << (unsigned int)(-val) << endl;

实验结果

val = -2147483648
4
4
2147483648
2147483648

2147483648
2147483648
2147483648

结论,如果就算一个int型的整数的绝对值,不能只考虑使用对负数取负或者使用math.h的abs()函数,需要进行相应的数位扩展。比如说,
1.将int转化为long long int,然后利用abs的重载功能计算;
2.或者转化为unsigned int,会直接将符号位看做数值部分。

实验2: 对普通整数

实验代码

int main()
{
    int val = 5;
    cout << -(unsigned int)val << endl;
    cout << (unsigned int)val << endl;
    cout << (unsigned int)(-val) << endl;
    cout << endl;
    val = -5;
    cout << -(unsigned int)val << endl;
    cout << (unsigned int)val << endl;
    cout << (unsigned int)(-val) << endl;
    return 0;
}
4294967291
5
4294967291

5
4294967291
5

因此,使用unsigned int获取整数绝对值需要考虑正负号。

计算一个数的绝对值

如果需要计算任意一个int类型的数的绝对值,不能直接使用abs函数,因为-2147483648的abs函数计算结果仍然是-2147483648,当然如果非要用abs函数,可以将-2147483648当做特殊情况单独处理即可,因为abs函数对除-2147483648的计算结果都是正确的。
如果在某些情况下不能用库函数,则可以采用如下方式:
实验代码

int main()
{
    int val = -5;
    unsigned int absVal = 0;
    if(val < 0)
    {
        //以下两条语句结果一样
        absVal = (unsigned)(-val);
        absVal = -(unsigned)(val);
    }
    else
    {
        absVal = (unsigned)val;
    }
    cout <<absVal << endl;

    return 0;
}
  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值