zoukankan      html  css  js  c++  java
  • 逻辑运算的妙用-Single Number

    题目:一个int的array,除了一个元素只有一个其余的都是两个,找到这一个的元素。

    使用:逻辑运算 XOR异或运算

    关于逻辑运算的总结【转】

    &&和||:逻辑运算符

    &和|:按位运算符

    &&是且的意思,a&&b 两者都为真才为真.
    
    ||是或的意思,a||b 两者有一为真即真.
    
    
    
    &,|是位运算符.即对位进行运算,
    
    如00000011 & 00000001=00000001
    
    00000011 | 00000001=00000011 

    对于(&&,||),运算的对象是逻辑值,也就是True/False
    运算结果只有下列四种情况。
    True  && True  = True
    True  && False = False
    False && True  = False
    False && False = False

    True  || True  = True
    True  || False = True
    False || True  = True
    False || False = False

    对于(&,|),运算的对象是位,也就是1/0
    运算结果只有下列四种情况。
    1 & 1 = 1
    1 & 0 = 0
    0 & 1 = 0
    0 & 0 = 0

    1 | 1 = 1
    1 | 0 = 1
    0 | 1 = 1
    0 | 0 = 0

    &&和&对于他们各自的运算对象来说,结果是一样的。
    同理,||和|也是一样的。

    比如:5&&2 的运算结果,是这样对待的。
    首先5,非零,即为True
    2,非零,True 
    True&&True = True

     微笑

    请往下看:

    使用位运算的好处是可以将BYTE,   WORD   或   DWORD   作为小数组或结构使用。通过位运算可以检查位的值或赋值,也可以对整组的位进行运算。

    16进制数及其与位的关系 
    用0或1表示的数值就是二进制数,很难理解。因此用到16进制数。 

    16进制数用4个位表示0   -   15的值,4个位组成一个16进制数。也把4位成为半字节(nibble)。一个BYTE有二个nibble,因此可以用二个16进制数表示一个BYTE。如下所示:

    NIBBLE       HEX   VALUE 
    ======       ========= 
      0000                 0 
      0001                 1 
      0010                 2 
      0011                 3 
      0100                 4 
      0101                 5 
      0110                 6 
      0111                 7 
      1000                 8 
      1001                 9 
      1010                 A 
      1011                 B 
      1100                 C 
      1101                 D 
      1110                 E 
      1111                 F 

    如果用一个字节存放字母 "r "(ASCII码114),结果是: 
    0111   0010         二进制 
        7         2           16进制 

    可以表达为: '0x72 ' 

    有6种位运算: 
          &       与运算 
          |       或运算 
          ^       异或运算 
          ~       非运算(求补) 
        > >       右移运算 
        < <       左移运算 

    与运算(&) 
    双目运算。二个位都置位(等于1)时,结果等于1,其它的结果都等于0。 
          1       &       1       ==       1 
          1       &       0       ==       0 
          0       &       1       ==       0 
          0       &       0       ==       0 

    与运算的一个用途是检查指定位是否置位(等于1)。例如一个BYTE里有标识位,要检查第4位是否置位,代码如下:

    BYTE   b   =   50; 
    if   (   b   &   0x10   ) 
            cout   < <   "Bit   four   is   set "   < <   endl; 
    else 
            cout   < <   "Bit   four   is   clear "   < <   endl; 

    上述代码可表示为: 

            00110010     -   b 
        &   00010000     -   &   0x10 
      ---------------------------- 
            00010000     -   result 

    可以看到第4位是置位了。 

    或运算(   |   ) 
    双目运算。二个位只要有一个位置位,结果就等于1。二个位都为0时,结果为0。 
          1       |       1       ==       1 
          1       |       0       ==       1 
          0       |       1       ==       1 
          0       |       0       ==       0 

    与运算也可以用来检查置位。例如要检查某个值的第3位是否置位: 

    BYTE   b   =   50; 
    BYTE   c   =   b   |   0x04; 
    cout   < <   "c   =   "   < <   c   < <   endl; 

    可表达为: 

            00110010     -   b 
        |   00000100     -   |   0x04 
        ---------- 
            00110110     -   result 

    异或运算(^) 
    双目运算。二个位不相等时,结果为1,否则为0。 

          1       ^       1       ==       0 
          1       ^       0       ==       1 
          0       ^       1       ==       1 
          0       ^       0       ==       0 

    异或运算可用于位值翻转。例如将第3位与第4位的值翻转: 

    BYTE   b   =   50; 
    cout   < <   "b   =   "   < <   b   < <   endl; 
    b   =   b   ^   0x18; 
    cout   < <   "b   =   "   < <   b   < <   endl; 
    b   =   b   ^   0x18; 
    cout   < <   "b   =   "   < <   b   < <   endl; 

    可表达为: 

            00110010     -   b 
        ^   00011000     -   ^0x18 
        ---------- 
            00101010     -   result 

            00101010     -   b 
        ^   00011000     -   ^0x18 
        ---------- 
            00110010     -   result 

    非运算(~) 
    单目运算。位值取反,置0为1,或置1为0。非运算的用途是将指定位清0,其余位置1。非运算与数值大小无关。例如将第1位和第2位清0,其余位置1: 

    BYTE   b   =   ~0x03; 
    cout   < <   "b   =   "   < <   b   < <   endl; 
    WORD   w   =   ~0x03; 
    cout   < <   "w   =   "   < <   w   < <   endl; 

    可表达为: 

            00000011     -   0x03 
            11111100     -   ~0x03     b 

            0000000000000011     -   0x03 
            1111111111111100     -   ~0x03     w 

    非运算和与运算结合,可以确保将指定为清0。如将第4位清0: 

    BYTE   b   =   50; 
    cout   < <   "b   =   "   < <   b   < <   endl; 
    BYTE   c   =   b   &   ~0x10; 
    cout   < <   "c   =   "   < <   c   < <   endl; 

    可表达为: 

            00110010     -   b 
        &   11101111     -   ~0x10 
        ---------- 
            00100010     -   result 

    移位运算(> >   与   < <) 
    将位值向一个方向移动指定的位数。右移   > >   算子从高位向低位移动,左移   < <   算子从低位向高位移动。往往用位移来对齐位的排列(如MAKEWPARAM,   HIWORD,   LOWORD   宏的功能)。

    BYTE   b   =   12; 
    cout   < <   "b   =   "   < <   b   < <   endl; 
    BYTE   c   =   b   < <   2; 
    cout   < <   "c   =   "   < <   c   < <   endl; 
    c   =   b   > >   2; 
    cout   < <   "c   =   "   < <   c   < <   endl; 

    可表达为: 
            00001100     -   b 
            00110000     -   b   < <   2 
            00000011     -   b   > >   2 

    译注:以上示例都对,但举例用法未必恰当。请阅文末链接的文章,解释得较为清楚。 

    位域(Bit   Field) 
    位操作中的一件有意义的事是位域。利用位域可以用BYTE,   WORD或DWORD来创建最小化的数据结构。例如要保存日期数据,并尽可能减少内存占用,就可以声明这样的结构:

    struct   date_struct   { 
            BYTE       day       :   5,       //   1   to   31 
                          month   :   4,       //   1   to   12 
                          year     :   14;     //   0   to   9999 
            }date; 
            
    在结构中,日期数据占用最低5位,月份占用4位,年占用14位。这样整个日期数据只需占用23位,即3个字节。忽略第24位。如果用整数来表达各个域,整个结构要占用12个字节。

    |   0   0   0   0   0   0   0   0   |   0   0   0   0   0   0   0   0   |   0   0   0   0   0   0   0   0   |
          |                                                           |                   |                     |
          +-------------   year   --------------+   month+--   day   --+ 

    现在分别看看在这个结构声明中发生了什么 

    首先看一下位域结构使用的数据类型。这里用的是BYTE。1个BYTE有8个位,编译器将分配1个BYTE的内存。如果结构内的数据超过8位,编译器就再分配1个BYTE,直到满足数据要求。如果用WORD或DWORD作结构的数据类型,编译器就分配一个完整的32位内存给结构。

    其次看一下域声明。变量(day,   month,   year)名跟随一个冒号,冒号后是变量占用的位数。位域之间用逗号分隔,用分号结束。 

    使用了位域结构,就可以方便地象处理普通结构数据那样处理成员数据。尽管我们无法得到位域的地址,却可以使用结构地址。例如: 
    date.day   =   12; 
    dateptr   =   &date; 
    dateptr-> year   =   1852;

  • 相关阅读:
    使用NBU进行oracle异机恢复
    mycat偶尔会出现JVM报错double free or corruption并崩溃退出
    exp导出数据时丢表
    service_names配置不正确,导致dg创建失败
    XML概念定义以及如何定义xml文件编写约束条件java解析xml DTD XML Schema JAXP java xml解析 dom4j 解析 xpath dom sax
    HTTP协议简介详解 HTTP协议发展 原理 请求方法 响应状态码 请求头 请求首部 java模拟浏览器客户端服务端
    java集合框架容器 java框架层级 继承图结构 集合框架的抽象类 集合框架主要实现类
    【JAVA集合框架一 】java集合框架官方介绍 Collections Framework Overview 集合框架总览 翻译 javase8 集合官方文档中文版
    java内部类深入详解 内部类的分类 特点 定义方式 使用
    再谈包访问权限 子类为何不能使用父类protected方法
  • 原文地址:https://www.cnblogs.com/liumeng-blog/p/5210749.html
Copyright © 2011-2022 走看看