• 用位运算求一个数的绝对值


         我们知道在我们对一个数进行位运算的时候,是在这个数的补码上进行的,对于补码我们知道,正数的补码是原码,负数的补码为原码除了最高位的符号位,取反,然后加1。把补码转换成原码的时候,正数还是原码,负数时把补码除了符号位取反然后加1(我们可以发现如果这时候连符号位也求反,然后加1,与以前不同的只是少了一个符号位,现在实际上就是这个数的绝对值)。所以我们可以得到对一个负数求绝对值的表达式为

    1. int SignReversal(int a)  
    2. {  
    3.     return ~a + 1;  
    4. }

    那么由这些知识我们可以很快地得到求一个数的绝对值的表达式:

    先移位来取符号位,int i = a >> 31;要注意如果a为正数,i等于0,为负数,i等于-1。然后对i进行判断——如果i等于0,直接返回。否之,返回~a+1。完整代码如下:

    [cpp] view plaincopy
     
    1. //by MoreWindows( http://blog.csdn.net/MoreWindows )  
    2. int my_abs(int a)  
    3. {  
    4.     int i = a >> 31;  
    5.     return i == 0 ? a : (~a + 1);  
    6. }  

    现在再分析下。对于任何数,与0异或都会保持不变,与-1即0xFFFFFFFF异或就相当于取反。因此,a与i异或后再减i(因为i为0或-1,所以减i即是要么加0要么加1)也可以得到绝对值。所以可以对上面代码优化下:

    [cpp] view plaincopy
     
    1. //by MoreWindows( http://blog.csdn.net/MoreWindows )  
    2. int my_abs(int a)  
    3. {  
    4.     int i = a >> 31;  
    5.     return ((a ^ i) - i);  
    6. }  

    而且有些笔面试题就要求这样做(比如不让用if语句的时候),因此建议读者记住该方法

  • 相关阅读:
    对fork函数的疑惑,求解!
    C语言获取集合幂集
    C#编写socket客户端,服务器断开连接时客户端报异常
    转载:Linux下的 .o、.a、.so文件
    浅析23种软件设计模式
    Linux之设备文件
    printf输出格式
    光放大器的工作波长
    QSYS组件信号命名方式
    摩尔定律
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3236802.html
Copyright © 2020-2023  润新知