博客
关于我
位运算(整数的二进制处理方法)JZ11、12、面试题56-I、64、65
阅读量:514 次
发布时间:2019-03-07

本文共 3401 字,大约阅读时间需要 11 分钟。

为了求两个整数之和而不使用加法、减法、乘法或除法运算符,我们可以使用二进制位运算来模拟加法过程。

问题分析:我们需要找到两个整数之和,但不允许使用任何数学运算符。可以借助二进制运算来完成加法。这是因为加法在二进制中可以通过异或和位移运算来处理。

方法详解:

  • 具体步骤如下:

    • 异或运算(XOR):异或两个数可得到每一位相加不产生进位的结果。
    • 与运算(AND):与两个数可得到哪一位相加产生了进位。
    • 进位处理:将产出的进位左移一位(即乘以2),重复上述过程,直到没有进位为止。
  • 逐步解释:

    • 1.首先计算异或结果(sum = a ^ b),这给出了不考虑进位的加法结果。
    • 2.然后计算进位(carry = (a & b) << 1)。因为当a和b的某位都为1时,才会产生进位。
    • 3.重复上述过程,直到没有进位。每次循环再计算新的sum为sum ^ carry,新的进位为(sum & carry) << 1。
    • 4.当进位为零时,循环结束,返回总和。
  • 示例:

    • 输入:a=3(二进制11),b=1(二进制01)
    • 步骤:
    • sum = 11 ^ 01 = 10(2),carry = 01 <<1 = 10(2)
    • sum = 10 ^ 10 = 00,carry = 00 <<1 = 00,循环结束
    • 返回sum=00=0。正确!实际应为4,哦,这里我们需要检查错误。

    你可能需要修正算法。让我们重新计算:

    • 修正后的算法:
    • sum = a ^ b
    • carry = (a & b) << 1
    • while carry != 0:
    • sum = sum ^ carry
    • carry = (sum & carry) << 1
    • 返回sum

    使用上述算法:

    • a=3,b=1:
    • sum = 11 ^ 01 = 10(2)
    • carry = 11 & 01 <<1 = 01 <<1 = 10(2)
    • sum = 10 ^ 10 = 00(0)
    • carry = (00 & 10) <<1 = 10 <<1=100(4)
    • sum = 00 ^ 100 =100(4)
    • carry = (100 & 100) <<1=00000000(0)
    • 循环结束,返回sum=100(4),正确!

    另一个示例: a=6(110),b=2(010)。

    • sum = 110 ^ 010=100(4)
    • carry= (110 & 010)=010 <<1=100(4)
    • sum=100 ^100=000(0)
    • carry=(000 &100)=00000000
    • 循环结束,返回sum=0,后面还有100和 0?不对,似乎算法还有问题。

    我需要重新检查和纠正这个错误:

    正确的步骤应是:

  • sum = a ^ b
  • carry = (a & b) <<1
  • while carry !=0:a. sum = sum ^ carryb. carry = (sum & carry) <<1
  • 返回sum
  • 对于a=3,b=1:

  • sum=2(10)
  • carry=2(10)
  • 循环:
    • sum = 2 ^2=0
    • carry=(0 &2)=0<<1=0
  • 返回0,这是错误的。哦,这里发现问题。
  • 实际上,我应该重新思考进位的处理方法:进位等于(a & b) <<1,而不是(sum & carry)应该在下一次循环中处理。

    或许,我需要调整算法:

    初始化sum = a ^ b,carry = (a & b) <<1,如下所示:

    int add(int a, int b) {int sum = a ^ b;int carry = (a & b) <<1;while(carry !=0) {sum = sum ^ carry;carry = (sum & carry) <<1;}return sum;}

    让我们测试a=3,b=1:

    sum = 2,carry=2第一次循环:sum = 2 ^2=0carry= (0 &2)=0<<1=0循环结束返回sum=0。这显然不对,正确答案应为4。

    对此,解决方法是当计算完第一次sum和carry后,将新的sum作为下一轮的计算基准,需要处理进位。或者,应将第二次的carry包括进位的高位进位。

    正确的处理方法面对负数吗?比如考虑进位时有可能导致高位溢出,而在Python中不受影响。

    可能需要修改算法,正确处理进位:

    int add(int a, int b) {int sum = a ^ b;int carry = (a & b) <<1;while(carry !=0) {sum = sum ^ carry;carry = (sum & carry) <<1;}return sum;}

    对于a=3,b=1:sum=2 → a=3(11),b=1(01)carry=01 <<1=10(2)sum=2 ^2=0 → 00carry=0 &2=0<<1=0,循环结束。返回0,这错误。

    这让我意识到,我在算法中错误地处理了进位。正确的进位应该是 (sum & carry),而我好像混淆了步骤。

    可能需要另一个方法:

    正确的算法应该是:

    int add(int a, int b) { // C++中无符号整数的处理while(b !=0) {int sum = a ^ b;int carry = (a & b) <<1;a = sum;b = carry;}return a;}

    这个算法会正确处理进位:

    测试a=3,b=1:

    • sum =11 ^ 01=10,carry=01<<1=10
    • a=10, b=10
    • new sum=10 ^ 10=00,carry= (10 &10)<<1= 100
    • a=00, b=100
    • next iteration:sum=00 ^100=100, carry=0000000000loop ends.
    • return a=100=4,正确。

    对于a=6,b=2:

    • a=6(110), b=2(010)
    • sum=110 ^010=100(4)
    • carry=010 <<1=100(4)
    • a=100, b=100
    • sum=100^100=000 (0)
    • carry=000 &100=000 <<1=00000000
    • loop stops, return a=000=0这仍不正确,正确的sum应为8=1000。

    哦,看来这个算法在这种情况下失败。

    正确的代码应:

    int add(int a, int b) {int carry;while (b != 0) {carry = a & b;a = a ^ b;b = carry << 1;}return a;}

    测试:

    a=3,b=1:

    • carry =11&01=01 → 1
    • a =11 ^01=10 (2)
    • b=01<<1=10(2)
    • Next iteration:carry =10 &10=10 →2a =10 ^ 10=00(0)b=10<<1=100(4)
    • Next iteration:carry=00 &100=00a=00 ^100=100(4)b=00 <<1=00Loop stops,return a=4,正确。

    对于a=6(110),b=2(010):

    • carry=110 &010=010 →2
    • a=110^010=100(4)
    • b=010<<1=100(4)
    • Next iteration:carry=100 &100=100 →4a=100^100=000(0)b=100<<1=1000(8)
    • Next iteration:carry=000 &1000=0000a=0^1000=1000(8)b=0000 <<1=0Return a=8,正确!

    这样,正确的代码版本应为:

    int add(int a, int b) {int carry;while (b != 0) {carry = a & b;a = a ^ b;b = carry << 1;}return a;}

    这样,就能正确地返回两个整数之和,且不使用加法运算符。

    结论:通过利用异或和位移运算,模拟二进制加法过程,我们可以在不使用加法运算符的情况下求两个整数之和。这种方法有效地处理了所有情况,包括进位和负数的情况,符合题目要求。

    转载地址:http://luunz.baihongyu.com/

    你可能感兴趣的文章
    power english (1) —— passion
    查看>>
    Power English (1) 原文
    查看>>
    power English (3)原文
    查看>>
    POWER ENGLISH(7)- repetition
    查看>>
    SpringBoot中集成SpringBatch详细解析与实战示例(CSV文件读取十万条数据进行业务处理后写入Mysql数据库)
    查看>>
    powerbi 一张表在另外一张表中出现的数量_PowerBi之初步学习笔记
    查看>>
    QGIS怎样设置简体中文以及新建可编辑的多边形的图层
    查看>>
    PowerBuilder 使用自定义事件触发键盘Enter事件
    查看>>
    PowerCreatorCMS UploadResourcePic 任意文件上传漏洞复现
    查看>>
    PowerDesigner 使用的一些技巧(转)
    查看>>
    QGIS在Windows上下载安装与建立空间数据库连接
    查看>>
    PowerDesigner165安装婆姐汉花教程
    查看>>
    PowerDesigner使用教程:设置注释、默认值属性
    查看>>
    PowerDesigner使用教程:不显示背景网格
    查看>>
    PowerDesigner使用教程:创建数据模型以及导出
    查看>>
    PowerDesigner使用教程:右侧工具栏显示/隐藏
    查看>>
    PowerDesigner使用教程:导出sql文件以及解决中文乱码问题
    查看>>
    PowerDesigner使用教程:时间字段设置
    查看>>
    PowerDesigner使用教程:给字段添加唯一约束
    查看>>
    QGIS中怎样设置图层样式并导出地图样式
    查看>>