【算法】【位运算模块】使用位运算完成整数的加减乘除

news/2024/10/31 7:29:48/

目录

  • 前言
  • 问题介绍
  • 解决方案
  • 代码编写
    • java语言版本
    • c语言版本
    • c++语言版本
  • 思考感悟
  • 写在最后

前言

当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批评指正~

在此感谢左大神让我对算法有了新的感悟认识!

问题介绍

原问题
使用位运算完成整数的加减乘除

解决方案

原问题
加法:
1、二进制数如果不考虑进位,异或运算就是加法结果
2、二进制计算进位的方法,使用&操作可以判断当前位是否进位,因为只有1和1会有进位,也只有1和1&操作是1
3、结合1、2两点,当前两个数a和b的异或结果为无进位相加,两个数的与操作为各位的进位,进位左移一位后加上异或的结果即为最终结果,剩下的操作循环即可,直到没有进位为止
减法:
a-b <=> a + (-b),而负数为正数的补码,剩下的过程和加法相同
乘法:
ab
按照正常的乘法法则计算即可
b中的1的位数代表a左移的位数,剩下的相加即可
除法:
a/b
除法为乘法的反推过程,从最大值开始枚举,首先商的31位为1时,乘b的结果小于a,则当前位商1,如果大于a则继续计算30位…
每商1时,a减去对应b

代码编写

java语言版本

原问题:

    /*** 返回a的补码:除了符号位以外,剩下的位取反+1,* 其实等价于该数的正数连通符号为直接取反+1* @param a* @return*/public static int negNum(int a){return addCp1(~a, 1);}/*** a+b* @param a* @param b* @return*/public static int addCp1(int a, int b) {int sum = a;while (b != 0) {// 无进位结果int x = sum ^ b;// 进位b = (sum & b) << 1;sum = x;}return sum;}/*** a-b* @param a* @param b* @return*/public static int subCp1(int a, int b) {// a+ b的补码即可,取反+1,符号位一起计算return addCp1(a, negNum(b));}/*** 获取当前值的补码* @param a* @return*/public static int negNumCp1(int a) {return addCp1(~a, 1);}/*** a * b* @param a* @param b* @return*/public static int multiCp1(int a, int b) {int res = 0;while (b != 0) {if ((b & 1) != 0) {res = addCp1(res, a);}b >>>= 1;a <<= 1;}return res;}/*** 除法最通常的情况* 但是有个缺陷就是 补码的负数比正数多一个最小值,最小值无法转正数所以当最小值计算时需要另外判断* @param a* @param b* @return*/public static int divCp1(int a, int b) {// 这里去一下符号int x = a < 0 ? negNumCp1(a) : a;int y = b < 0 ? negNumCp1(b) : b;// 商int res = 0;// 因为不能存在算数计算,所以这里--i也用的sub函数减法for (int i = 31; i >= 0; i = subCp1(i, 1)) {// 先尝试除数b左移位i位是否小于等于被除数aif ((x >> i) >= b) {// 说明商1res |= 1 << i;// 减x = subCp1(x, y << i);}}return res;}/*** 考虑了全部情况的除法* @return*/public static int divideCp1(int a, int b) {if (b == 0) {throw new RuntimeException("除数为0");}if (a == Integer.MIN_VALUE && b == Integer.MIN_VALUE) {return 1;}else if (a != Integer.MIN_VALUE && b == Integer.MIN_VALUE) {return 0;}else if (a == Integer.MIN_VALUE && b == Integer.MIN_VALUE) {// 首先计算a+1/bint res1 = divCp1(a+1, b);// 再乘回去求和原来值的差int sub = a - multiCp1(res1, b);// 返回结果,如果偏差值刚好满一个b,那么说明res1 + 1return res1 + sub/b;}else {// 最正常的情况return divCp1(a, b);}}public static void main(String[] args) {System.out.println(add(4, 2));}

c语言版本

正在学习中

c++语言版本

正在学习中

思考感悟

位运算的加减乘除是计算机专业中计算机组成课程中必修部分,现在使用代码实现起来仍然能够感受到二进制的博大精深。

写在最后

方案和代码仅提供学习和思考使用,切勿随意滥用!如有错误和不合理的地方,务必批评指正~
如果需要git源码可邮件给2260755767@qq.com
再次感谢左大神对我算法的指点迷津!


http://www.ppmy.cn/news/21357.html

相关文章

感谢第三弹 | 开启地铁国产化浪潮 GBASE获多方城市“地下动脉”肯定

岁末年初&#xff0c;GBASE收到了来自深圳地铁、高新现代智能系统股份有限公司、深圳达实智能股份有限公司等客户及合作伙伴发来的荣誉证书及感谢信。作为亲密无间的战友&#xff0c;GBASE携手高新现代、达实智能在深圳地铁CLC、ACC、AFC多个条线项目中通力合作&#xff0c;助力…

Cesium 内置变量、常量、函数-Shader

内置uniform 内置uniform主要置于AutomaticUniforms类里面,该类私有未开放文档。 czm_backgroundColor代表当前场景背景颜色的自动GLSL制服。 例: // GLSL声明 统一vec4 czm_backgroundColor; //示例:如果给定颜色的RGB与背景颜色匹配,则将其反转。 vec4 AdjustColorForCo…

【关于Linux中----信号】

文章目录一、信号入门1.1 信号概念1.2 用 kill-l命令查看信号列表1.3 信号处理常见方式预览二、产生信号2.1 通过终端按键产生信号2.2 由于程序中存在异常产生信号2.3 系统接口调用产生信号2.4 软件条件产生信号三、阻塞信号3.1 信号相关常见概念补充3.2 在内核中的表示3.3 sig…

JVM的类加载

什么是类加载&#xff1f;java程序运行前&#xff0c;要经过编译即.java>.class文件。运行的时候java进程(JVM)就会读取对应的.class文件&#xff0c;并解析内容&#xff0c;在内存中构造出类对象并进行初始化&#xff08;类对象就是描述这个类有哪些属性&#xff0c;哪些方…

阿里JAVA开发手册(泰山版)

目录 前言 一、编程规约 &#xff08;一&#xff09;命名风格 &#xff08;二&#xff09;常量定义 &#xff08;三&#xff09;代码格式 &#xff08;四&#xff09;OOP 规约 &#xff08;五&#xff09;日期时间 &#xff08;六&#xff09;集合处理 &#xff08;七…

base64 编码、解码

import base64a base64.b64encode(这是dage.encode(utf-8)) #base64 编码print(a)# b6LZ5pivZGFnZQstr(a, utf-8)print(str(a, utf-8))# 6LZ5pivZGFnZQbase64.b64decode(a) #base64 解码print(base64.b64decode(a))# b\xe8\xbf\x99\xe6\x98\xafdagestr(base64.b64decode(a), u…

数据结构——优先级队列和堆

目录 一、堆 1.概念 2.堆的存储方式 3.性质 4.模拟实现堆&#xff08;以小根堆为例&#xff09; &#xff08;1&#xff09;.堆的调整 &#xff08;2&#xff09;.堆的创建 &#xff08;3&#xff09;.建堆的时间复杂度 &#xff08;4&#xff09;.堆的插入和删除 5.堆…

MyBatis(三)使用MyBatis完成CRUD(增删改查)

准备工作 1、创建module&#xff08;Maven的普通Java模块&#xff09;&#xff1a;mybatis-002-crud 2、pom.xml 打包方式jar依赖&#xff1a;mybatis依赖mysql驱动依赖junit依赖logback依赖3、mybatis-config.xml放在类的根路径下 4、CarMapper.xml放在类的根路径下 5、lo…