C++中关系运算符的效率问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++中关系运算符的效率问题相关的知识,希望对你有一定的参考价值。

if(i > 101)与if(i >= 100)

哪个效率好一些?为什么?

应该效率是一样的。

我用gcc试着编译了一个简单的代码,用-S选项输出编译出来的汇编代码,

发现当把 i>100 改成 i>=100 之后,汇编代码里唯一的变化是

可以看到编译器比较聪明的把常量的值修改了,这两种形式编译出来的结果实际上是完全一样的。

那么对于非常量的情况,我试了把 i>j 改成 i>=j,比较汇编代码的区别是:

这说明汇编语言里面有相应的指令分别表示 大于等于 和 大于。我想这两个指令在绝大多数的CPU上都是一个时钟周期出来的,所以效率也不会有差别。

参考技术A 第二个好一些,if(i >= 100)这个只用判定到i=100时候就不再往下进行了,if(i > 101)要判定到101,比前一个多一步,当然上边说的是循环判定中,i自增的情况下。

如果不涉及到循环,只是单纯的一步对比来说,两个效率一样,因为他们的二进制表示法只有最后一位不同而已。计算机中是按照二进制位来对比的。
参考技术B 这两个怎么比?范围都不一样 参考技术C 这两个表示的范围不同。

Java中关于位运算的面试题

位运算的效率是最高的,因为位位运算是直接对二进制进行操作

位运算只能应用于整型和char类型(char类型可以看做是特殊的无符号的整形)

面试题:
    a: 判断一个数是否是奇数 a & 1 == 1;
    b: 对2 ^ n 取余。 a & (2^n - 1);
    c: 如何判断一个数是否是2^n a & (a-1) == 0;
    d: 两个整数之间的交换;
    e: 用最有效率的方式求2 * 8的值 2 << 3;

 

a: 判断一个数是否是奇数 a & 1 == 1;

/*
判断一个数是否是奇数?
    特点:最低位为1.
    a & 1 == 1;
*/
class OperatorDemo1 
    public static void main(String[] args) 
        int a = -2018;
        // System.out.println(a % 2 == 1);
        // System.out.println(a % 2 != 1);
        System.out.println((a & 1) == 1);
    

b: 对2 ^ n 取余。 a & (2^n - 1);

/*
对2的n次幂取余,都可以转换成位运算。
2^n: 
    1101 1101
%    0100 0000

    1101 1101
&    0011 1111
     
*/
class OperatorDemo3 
    public static void main(String[] args) 
        int a = 2019;
        System.out.println(a % 64);
        System.out.println(a & (64 - 1));
        
        /*System.out.println(a % 78);
        System.out.println(a & (78 - 1));*/
    

c: 如何判断一个数是否是2^n

     a & (a-1) == 0;

/*
判断一个数是否是2的n次幂?
    2^n:因子都是2;
    时间复杂度:logn;
    
能否在常量时间复杂度内, 判断一个数是否是2的n次幂。
    2^n的存储特点:只有一个1,后面全部是0.
    (a & (a - 1)) == 0
    
    0100 0000
&    0011 1111
    0000 0000
    
    0101 0000
&    0100 1111
    0100 0000
*/

class OperatorDemo4 
    public static void main(String[] args) 
        int a = 1024;
        System.out.println((a & (a - 1)) == 0);
    

d: 两个整数之间的交换;

/*
面试题
    两个整数变量的交换.
*/

class OperatorDemo5 
    public static void main(String[] args) 
        // 方式一
        /*int a = 4;
        int b = 3;
        System.out.println("a=" + a + ", b=" + b);
        int temp = a;
        a = b;
        b = temp;
        System.out.println("a=" + a + ", b=" + b);*/
        
        // 方式二
        // 加法和减法互为逆运算。
        /*int a = 4;
        int b = 3;
        System.out.println("a=" + a + ", b=" + b);
        a = a + b; // a = 4 + 3, b = 3;
        b = a - b; // a = 4 + 3, b = 4 + 3 - 3 = 4;
        a = a - b; // a = 4 + 3 - 4 = 3, b = 4;
        System.out.println("a=" + a + ", b=" + b);*/
        
        // 方式三
        /*int a = 4;
        int b = 3;
        System.out.println("a=" + a + ", b=" + b);
        a = a ^ b; // a = 4 ^ 3, b = 3
        b = a ^ b; // a = 4 ^ 3, b = 4 ^ 3 ^ 3 = 4;
        a = a ^ b; // a = 4 ^ 3 ^ 4 = 3, b = 4;
        System.out.println("a=" + a + ", b=" + b);*/
        
        // 方式四
        int a = 4;
        int b = 3;
        System.out.println("a=" + a + ", b=" + b);
        /*a = a ^ b; 
        b = b ^ a; 
        a = a ^ b; */
        // a ^= b ^= a ^= b;
        a = (a ^ b) ^ (b = a); //工作中千万别这样写, 太show了。写代码,简洁易懂。
        System.out.println("a=" + a + ", b=" + b);
    

e: 用最有效率的方式求2 * 8的值 2 << 3;

/*
<< 左移: 低位补0,高位丢弃
>> 右移: 高位补符号位, 低位丢弃
>>>无符号右移: 高位补0,低位丢弃

注意事项;
    左移:左移n个单位,相当于乘以2^n;
    右移: 右移n个单位,相当于除以2^n;
    
    对于移位运算符来说,当操作数超出了字长时,实际移动 n mod 字长 个单位。
    
练习:
    用最有效率的方式写出计算2乘以8的结果
    2 << 3
*/

class OperatorDemo7 
    public static void main(String[] args) 
        int a = 192;
        System.out.println(a << 2); // 192 * 4 = 768
        System.out.println(a >> 2); // 192 * 4 = 48
        System.out.println(-a >> 2); // -192 * 4 = -48
        
        System.out.println(a >>> 2);// 48
        System.out.println(-a >>> 2); // 很大的整数
        
        System.out.println("-----------------------");
        a = 64;
        System.out.println(a >>> 32);         
        System.out.println(a << 32); 
        System.out.println(a >> 32);         
        System.out.println(a >> 33);         
        System.out.println(a >> -31);         
        
        
    


/*
192:
    0000 0000 0000 0000 0000 0000 1100 0000
<<  2                        
    0000 0000 0000 0000 0000 0011 0000 0000
    
192:
    0000 0000 0000 0000 0000 0000 1100 0000
>>  2                        
    0000 0000 0000 0000 0000 0000 0011 0000

-192:
    1111 1111 1111 1111 1111 1111 0100 0000
>> 2
    1111 1111 1111 1111 1111 1111 1101 0000

192:
    0000 0000 0000 0000 0000 0000 1100 0000
>>>  2                        
    0000 0000 0000 0000 0000 0000 0011 0000
    
-192:
    1111 1111 1111 1111 1111 1111 0100 0000
>>> 2
    0011 1111 1111 1111 1111 1111 1101 0000
*/

 

以上是关于C++中关系运算符的效率问题的主要内容,如果未能解决你的问题,请参考以下文章

第四章----关系代数运算

C++中关于&运算符的问题

C#中 Lambda表达式 与正则表达式的关系

基于 MySQL 的数据库实践(更名运算)

C++中关于string类型究竟能不能用cout输出的问题

Java中关于位运算的面试题