• 使用位运算求整数的绝对值


    一、整数的基础知识

    1. int在内存中占4个字节,32位。

    2.int在内存中以补码的形式表示。

    1)正数的原码、反码、补码都是一样的。

    2)负数的补码=负数的原码除符号位外取反,然后加1

    所以,在内存中,-1和1的表示差别不仅仅在符号位。

    二、右移运算符

     右移运算符指高位按符号位进行填充。即正数用0填充,负数用1填充。

    因此,若定义int x,那么 x>>31,若x为正数,结果是0,若x为负数,结果是0Xffffffff,也就是-1的补码。因为整数在内存中就是用补码表示,所以,0Xffffffff就是-1。

    三、异或运算符

    异或可以理解为不进位加法,即1+1 = 0, 0+0=0,1+0=1。

    由上可知,任意整数与0异或,结果还是整数本身,与0Xffffffff异或,则是将该整数连同符号位在内一并取反。

    上面的知识是使用位运算求整数绝对值时需要用到的。下面再补充一些异或运算的其他知识。

    异或运算的四个性质:

    1)交换律

    可任意交换运算因子的位置,结果不变。  即a^b = b^a

    2)结合律

    (a^b)^c  =  a^(b^c)

    3)对于任何数x,都有x^x = 0, x^0 = x, 即同自己求异或为0,同0求异或为自己。

    4)自反性 

    连续和同一个因子做异或运算,最终结果为自己。

    A^B^B = A^0 = A

    四、使用位运算求整数的绝对值

    原理:

    负数的补码原码转补码是 除符号位取反加1,补码转原码也是 除符号位取反加1。如果我们求出了一个负数的原码,那么它的绝对值就是将这个原码的符号位取反即可(将1取反为0)。

    即:补码转原码时,除符号位都取反了,原码转绝对值时,符号位被取反了,那么,将这两次取反操作合在一起,即:对补码的所有位取反,然后加1,可得到该补码对应的负数的绝对值。

    C语言代码:

    int abs(int a)
    {
        int iMask = a>>31;
        a = a^iMask-iMask;
        return a;
    }
    

     

    或者:

    int abs(int a)
    {
        int iMask = a>>31;
        a = a^iMask;
      a = a-
    iMask;
    return a; }

     

    代码解析:

    当a为正数时:第一步,iMask=0,第二步,a异或0,结果a还是本身,第三步,a-0,结果还是a。符合正数的绝对值是其本身,代码成立。

    当a为负数时

    第一步,iMask=0Xffffffff,即-1的补码,因为整数在内存中用补码表示,所以iMask实际上就是-1;

    第二步,a异或0Xffffffff,即连同符号位在内对a取反,此时,符号位1变成0,即负号变成正号。

    第三步,a-iMask = a-(-1) = a+1,负数的补码 = 除符号位外取反加1,第二步将符号位变为正号,完成了绝对值的过程,第三步此处完成了负数数字部分的转变。这样就成功求出了负数的绝对值。

     

     

  • 相关阅读:
    使用.NET Core在RESTful API中进行路由操作
    基础教程:ASP.NET Core 2.0 MVC筛选器
    Angular 5和ASP.NET Core入门
    net core 使用tagHelper将 enum枚举类型转换为下拉列表select
    教你如何实现微信小程序与.net core应用服务端的无状态身份验证
    解决mssql localdb 中文乱码问题
    datagrid 新增,并行内编辑,提交保存
    合法的json数组字符串,转换json
    jfinal的回滚
    oracle 修改 字段名称
  • 原文地址:https://www.cnblogs.com/nanzhi/p/14247371.html
Copyright © 2020-2023  润新知