博客
关于我
位运算(整数的二进制处理方法)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/

    你可能感兴趣的文章
    Node出错导致运行崩溃的解决方案
    查看>>
    Node响应中文时解决乱码问题
    查看>>
    node基础(二)_模块以及处理乱码问题
    查看>>
    node安装卸载linux,Linux运维知识之linux 卸载安装node npm
    查看>>
    node安装及配置之windows版
    查看>>
    Node实现小爬虫
    查看>>
    Node提示:error code Z_BUF_ERROR,error error -5,error zlib:unexpected end of file
    查看>>
    Node提示:npm does not support Node.js v12.16.3
    查看>>
    Node搭建静态资源服务器时后缀名与响应头映射关系的Json文件
    查看>>
    Node服务在断开SSH后停止运行解决方案(创建守护进程)
    查看>>
    node模块化
    查看>>
    node模块的本质
    查看>>
    node环境下使用import引入外部文件出错
    查看>>
    node环境:Error listen EADDRINUSE :::3000
    查看>>
    Node的Web应用框架Express的简介与搭建HelloWorld
    查看>>
    Node第一天
    查看>>
    node编译程序内存溢出
    查看>>
    Node读取并输出txt文件内容
    查看>>
    node防xss攻击插件
    查看>>
    noi 1996 登山
    查看>>