• 实验名称:对位运算异或(^)的探究
  • 实验内容:编程实现

输入偶数个数,找出其中出现奇数次的两个数字

  • 分析
  1. 从系统输入n(n为偶数)个数字;
  2. 开一个动态数组把n个数字存起来,知道他们的地址
  3. 在输入n个数字的同时就开始处理他们,也就是进行位运算
  4. 然后得出答案

四、值得注意的问题:

1.首先我们要了解这个异或的的符号的作用,位运算的计算过程都是二进制的,所以我们要探究它的作用,很多情况下我们得自己手动操作。

2.异或的内容是:两个数的二进制0和1,进行比较,只有在比较两个位不同的时候结果才是1,(真),否则就是0(假);也就是输入的两个数,不同才为1,相同为0;

3.这里应该注意到一个细节,那就是0^n=n,0跟任何数异或之后都是那个数的本身,因为0就代表着假,那么那个数字非0也就是真,结果当然是1,如果那个数字是0的话,结果也就是0了,无论结果如何,我们都能知道那个数字是多少。

4:要找出这个答案,其实最难的是异或运算之后的操作,n个数字异或完,也就是那两个奇数次的数字之间的异或,比如:1 1 2 2 2 3 3 4  出现偶数相同的数字肯定异或之后就是0,所有出现偶数次的数字通过异或之后就都为0,那么我们就可以知道出现奇数次的数字异或之后肯定保留了下来,比如上面的例子  异或之后的结果就是 2^4  因为2和4两个数出现了奇数次。那要怎么进行分开呢?
5.最值得注意的问题就是接下来了,找到了两个出现奇数次的数字的异或结果了,可是这并不是分开的,是两个异或的结果,那么我们就要想一个办法把其中一个数字分开,也就能找出另一个数字了。
6.对,现在思路出来了,就要去找出一个方法去实现我们所想的,程序就是要通过人去构思,然后用程序去实现我们的想法。这是我对程序的编写的认识。
7.对异或这个符号的运算的概念一定要了解清楚,不然就无从下手了。异或通俗来说就是两个数如果相同那么就是0,不同就是1,这个符号其实就是要找不同的数字。
五、编程清单
#include<stdio.h>
int a[10000009];//开一个全局变量,申请更多的空间,在局部开的话,可能不够
int main()
{
    int i,n,x,v,s1,s2,k,t,t1;//n代表个数,v代表接下来所有数字异或之后的值,i是循环变量
    while(scanf("%d",&n)!=EOF)//EOF就是文件结束的意思  这里只是让我们能多次输入样例
    {
        v=0;//把V初始化为0,对接下来异或的运算不会产生影响,在前面我已经说清楚了,为什么要这样了。
        for(i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            v^=a[i];
        }
        s1=v;s2=v;//弄两个变量,是因为s1用来找两个数中的一个赋值的变量,s2是用来找到那个数之后异或一下就是另一个数
        k=0;//这里的k就是代表v出现1的位置
        while(!(s1&1))//这个循环就是用来找出异或v的二进制中从右往左遍历找它第一次出现1的位置
        {//s1&1 这个是算出s1二进制最末尾的值是0或1 循环条件是还没找到1,要接着找
            s1=s1>>1;//这也是一个位运算>>  这代表右移,因为你在它的二进制的最末尾没有找到1那肯定要把最末尾的那个数字去除,让它的上一位当最末尾,因为前面找1只能是在最末尾的
            k++;//末尾没有出现1,也就是要+1,说明从右往左开始数的第一不是1,K其实也就是从右往左开始数1第一次出现的位置
        }
//解释一下为什么找异或结果二进制出现第一个1的作用,首先我们要明白异或的运算,那两个出现奇数次的数字异或起来肯定是不同的,(不会出现相同的,如果是相同那不就违背了出现奇数次的数字了,两个相同的奇数次不就是偶数次吗? 啊哈哈哈)
//0^1=1  这就是异或,那为什么我找v的1的位置呢,因为在v的1的那个位置  那两个数字也在二进制那两个位置,那么肯定一个是0一个是1,这个我们不用管,接下我们就去遍历一下刚才输入的数在这个位置也出现1,说明就是这个数字了
        for(i=0;i<n;i++)//循环遍历找出现奇数次的那个数
            if((a[i]>>k)&1)//这个判断条件是因为找到了v的1在第几个位置,那么要找到我们需要的那个数,所以我右移K位跟v的位置一样,然后最末尾的就是我们要找的位置了  然后就看他是不是1了
                v^=a[i];//条件成立,就说明a[i]就是所找的那个数字了。直接对v异或就是 那个数字
       //a^b=v  v^a=b  v^b=a         
        printf("%d %d\n",v,v^s2);//v是刚才找到的那个数字,s2是两个数的异或 用v已知的数去异或也就找到了另一个数字了
}
return 0
}
编程运行的结果如下:
六、结果分析与调试
1.刚开始以为这个代码存在漏洞,如果出现是0的怎么办,想了很久,后面我发现我对题目没有理解清楚,它保证是会出现奇数次的两个,但我再想想,这不用说都知道啊,肯定啊,如果出现相同,那两个相同的奇数次不就是偶数次了,这不就是没出现奇数次的数字了吗?  所以出现结果0 那就是没有出现奇数次的数字了。
2.当初还遇到一个问题就是如果我遍历去找其中的一个数,如果没有的话,那不就是没有出现两个数字是出现奇数次的吗?我当时没有想到。
3.刚开始写的代码是没有考虑到位运算的,直接对每个数字进行奇数,然后再重新去遍历去找出现奇数次的个数,就是我们要找的。这个就用到了数组,可是我拿去系统评测,结果就是超时和越界,因为他给的数据都很大,如果输入的n为1千万,1亿呢,接下来输入的n个数也很大,难道我们用数组的下角标去标记够吗?很显然是不行的,如果我标记的数组开的不够大呢,那肯定会出现越界问题。
4.想了很久,向别人请教才知道用位运算来做很高效,然后我就去了解位运算的内容,果然很好用。我是ACM集训队成员,所以每天都在刷题,这个问题就是在OJ的网站遇到的,今天我了解了,我有自己的心得就写下来了。
七、结论
1.多思考,一条路行不通,我们就应该换应该思路去做,不是因为我们想不到,可能是这个方法的算术不够好,我们就应该找应该更好的算法来实现这个编程。
2.对位运算的符号&、^、>> 这几个符号我们一定要很了解,计算机的二进制我们应该利用起来,有时候看起来很繁琐,但也可能是非常的有用,我们应该利用我们身边所能利用的资源。
3.做这个题目我们应该先看到数据的范围,小数据我们可能用暴力的方法直接过,可是遇到大数据的话要怎么办呢。所以我们遇到问题的时候应该先看这个数据是不是很大,是很大的话,我们应该找一个好的算法来解决这个问题。
4.其实位运算的用途还有很多,在遇到大数据的时候其实是非常好用的,现在对位运算的了解还是不够,这是不足的地方,我希望以后学到了更多的,再写下自己的心得,还有位运算&,|,这两个,这两个位运算我运用的还不是很经常。
5.位运算的应用,极大方便了我们对数据的处理,这个位运算就想我所遇到的,数据大的时候明显不适合普通的算法去解决,用到它,极大提高了效率。
6.其实这个程序我觉得还能再稍微修改一下,我第一次循环遍历找到其中的一个数,如果这个数刚好出现在很前面,那我找到它了,我就直接跳出,就不需要再遍历我接下来的数组,这个只要找if的判断条件找之后,异或之后就直接跳出就行了。
7.如果输入的每个数值都很大的话,我们应该把数组的类型改成long long int   因为这个能让输入的数据更大。遇到什么清空,我们就应该想到一个去解决它。

位运算之异或运算的理解相关推荐

  1. Java中「与运算,或运算,异或运算,取反运算。」

    Java中「与运算,或运算,异或运算,取反运算.」 文章目录 Java中「与运算,或运算,异或运算,取反运算.」 Java中的「与运算(AND) & 」 规则 :都为1时才为1,否则为0 Ja ...

  2. 什么是异或_异或运算及异或运算的作用

    什么是异或_异或运算及异或运算的作用 异或,是一个数学运算符,英文为exclusive OR,缩写为xor,应用于逻辑运算. 异或的数学符号为"⊕",计算机符号为"xor ...

  3. java中的或运算_java中的(或运算,异或运算,与运算)

    java中或运算.异或运算.与运算的使用实例和解释如下: public class Test {    public static void main(String[] args) { // 1.左移 ...

  4. keil5中的或运算、与运算、异或运算理解

    之前一直不能理解寄存器中那些非常简洁的位运算符,如下 GPIOC->ODR^=(1<<8); 这里用数字代入证明理解下 1.或运算|= 用途:让某位输出高电平1 e.g. 让PX2输 ...

  5. 【Java位运算】异或运算的使用

    异或运算有个特性:两个相同的数做异或运算,结果为0. n ^ n = 0; 常用的方式是查找数组中只出现一次的数字. 例如:在一个数组中,只有一个数字出现了一次,其余数字都出现了两次. 求这个数字. ...

  6. 与运算,或运算,异或运算

    一:与运算 与运算符(&) 运算规则:0&0=0:0&1=0:1&0=0:1&1=1 同真为真,一假全假!(同为1才是1,有0就为0) 例如:3&5十进 ...

  7. labview实现异或运算_异或运算 XOR 教程

    大家比较熟悉的逻辑运算,主要是"与运算"(AND)和"或运算"(OR),还有一种"异或运算"(XOR),也非常重要. 本文介绍异或运算的含义 ...

  8. 与运算、或运算以及异或运算

    回顾了一下& | ^ 三个运算 做个笔记记录一下 1.与运算(&) 计算规则:两个计算的二进制数 相同位为1结果为1否则为0 1 & 1 = 1; 1 & 0 = 0; ...

  9. 学习笔记:与运算、或运算、异或运算

    与运算(&) 两位同时为1,结果为1,否则为0. 0&0为0,0&1为0,1&0为0,1&1为1 例: 126&24: 126二进制:0111 1110 ...

最新文章

  1. CloudCompare的介绍
  2. java 线程 Thread 使用介绍,包含wait(),notifyAll() 等函数使用介绍
  3. cacti + nagios + npc 整合部署
  4. 小腹下面是什么部位_为什么肚子上的肉最难减?说好的马甲线呢?
  5. WslRegisterDistribution failed with error: 0x8007019e The Windows Subsystem for Linux optional compo
  6. mysql一些常用操作_mysql的一些常用操作(一)
  7. MyEclipse 如何使用断点调试
  8. 前端基础之BOM和DOM
  9. Qt文档阅读笔记-void QObject::deleteLater()解析
  10. 【百度地图API】如何批量转换为百度经纬度
  11. nexus : maven上传jar包到nexus私服后的存放路径以及保存的数据结构
  12. 用Aliyun E-MapReduce集群的sqoop工具和数据库同步数据如何配置网络
  13. 寒冬中的一次优雅起舞
  14. 2010工作代码总结之三(repostioryItemGridLookUpEdit下拉框)
  15. 《Cascade R-CNN: Delving into High Quality Object Detection》论文解析
  16. Haar人脸检测:Haar特征 + Adaboost+ 级联分类器及改进
  17. AVFoundation照片/视频捕捉功能 小视频/直播
  18. Gauss-Seidel迭代法解线性方程组
  19. 熟悉RealView MDK集成开发环境(Keil uVision4)的使用
  20. 分别用if else 以及 switch实现 税收计算

热门文章

  1. 基于Python神经网络的手写字体识别
  2. Hadoop、Slurm平台详细安装配置步骤
  3. AD部分器件变绿,出现x>25.4mm提示时的解决办法
  4. 趣味数学:赚了多少和两只火鸡
  5. Linux笔记:串口通讯工具minicom基础使用
  6. 网络推广用的数据分析工具
  7. matlab求解时域特征参数,matlab 实现数据时域特征提取
  8. (杂谈四) 北京城の八月
  9. 吃鸡 python开发_python实现《吃鸡大法》加文字识别 玩转百万英雄!
  10. Mac安装VM虚拟机