使用位操作符实现加减乘除!

欢迎拜访:雾里看山-CSDN博客
本篇主题:使用位操作符实现加减乘除
发布时间:2025.1.1
隶属专栏:C语言

在这里插入图片描述

目录

  • 位操作实现加法运算(+)
    • 原理
    • 代码示例
  • 位操作实现减法运算(-)
    • 原理
    • 代码示例
  • 位操作实现乘法运算(*)
    • 原理
    • 代码示例
  • 位操作实现除法运算(/)
    • 原理
    • 代码示例
  • 简单的测试代码
  • 特别注意

以下是在C语言中通过位运算来模拟实现加减乘除运算的详细描述及代码示例:

位操作实现加法运算(+)

原理

利用位运算实现加法的基本思路来源于计算机中二进制数加法的过程,即通过逐位相加以及考虑进位来得到结果。可以使用异或( ^ )操作来模拟无进位的相加,用与( & )操作和左移( << )操作来模拟进位的产生,然后不断重复这个过程直到没有进位为止。

代码示例

int add(int a, int b) {int sum, carry;do {sum = a ^ b;  // 异或操作,模拟无进位相加carry = (a & b) << 1;  // 与操作获取进位,并左移一位a = sum;b = carry;} while (carry!= 0);return sum;
}

利用位运算模拟加法的过程,通过不断计算进位并进行无进位加法(异或操作)来实现整数相加。对于有符号整数,其位表示在计算机中是按照补码形式存储的,这种方法同样适用于补码表示的正负数相加。
循环直到进位为0,表示没有新的进位产生,此时的 a 就是相加后的结果。

位操作实现减法运算(-)

原理

减法可以转换为加法来实现,因为在计算机中,减去一个数等同于加上这个数的补码。求补码的方式是对原数按位取反后加1,在代码中可以先对减数取反(通过按位取反操作 ~ )然后再加1(可以调用上面实现的加法函数),最后与被减数进行加法操作即可实现减法。

代码示例

int subtract(int a, int b) {return add(a, add(~b, 1));  // a + (-b),先求b的补码(~b + 1),再与a相加
}

在计算机中,减去一个数等同于加上这个数的相反数。对于有符号整数,先通过按位取反操作 ~ 获取一个数补码表示下的“反码”,然后再加1就得到其相反数的补码表示,最后调用前面实现的加法函数来完成减法运算。

位操作实现乘法运算(*)

原理

乘法运算可以通过多次加法来模拟实现。例如,计算 a * b ,如果 b 的二进制表示中某一位为1,就把对应的 a 左移相应的位数后累加到结果中。通过循环检查 b 的每一位来完成这个过程。

代码示例

int multiply(int a, int b) {int result = 0;int sign = ((a < 0) ^ (b < 0))? -1 : 1;  // 判断结果的符号,异或运算确定正负情况a = (a < 0)? -a : a;  // 取绝对值b = (b < 0)? -b : b;while (b > 0) {if (b & 1) {  // 判断b的最低位是否为1result = add(result, a);}a = a << 1;  // a左移一位相当于乘以2b = b >> 1;  // b右移一位相当于除以2}return sign * result;  // 根据符号返回最终结果
}

首先确定结果的符号,通过判断两个操作数的正负情况,利用异或运算,如果两数正负不同则结果为负,相同则结果为正。
然后将两个操作数都取绝对值进行后续计算。乘法运算通过不断判断乘数( b )的最低位是否为1,如果是1就把被乘数( a )累加到结果中,之后 a 左移一位(相当于乘以2), b 右移一位(相当于除以2),重复这个过程直到 b 变为0。
最后根据之前确定的符号来返回正确的乘积结果。

位操作实现除法运算(/)

原理

除法运算可以通过不断地用被除数减去除数(利用前面实现的减法操作),并记录减法操作执行的次数来模拟实现。同时,为了处理符号以及提高效率,需要考虑一些边界情况和优化技巧,比如先判断被除数和除数的绝对值大小等情况。

代码示例

int divide(int dividend, int divisor) {if (divisor == 0) {  // 除数不能为0return -1;  // 可以根据实际情况返回合适的错误码或进行异常处理}int sign = ((dividend < 0) ^ (divisor < 0))? -1 : 1;  // 确定结果的符号int abs_dividend = (dividend < 0)? add(~dividend, 1) : dividend;  // 取被除数绝对值int abs_divisor = (divisor < 0)? add(~divisor, 1) : divisor;  // 取除数绝对值int quotient = 0;while (abs_dividend >= abs_divisor) {abs_dividend = subtract(abs_dividend, abs_divisor);quotient = add(quotient, 1);}return sign * quotient;
}

同样先确定结果的符号,然后把被除数和除数都取绝对值进行运算。
通过一个外层 while 循环,只要被除数大于等于除数,就尝试找到能从被除数中减去的除数的最大倍数。内层 while 循环不断左移除数,同时对应的倍数也不断左移(相当于乘以2),找到最大倍数后,从被除数中减去这个倍数对应的除数,同时把倍数累加到商中。
最后根据确定的符号返回正确的商。

简单的测试代码

以下是一个简单的测试主函数示例:

#include <stdio.h>int main() {int a = 5;int b = -3;printf("加法结果:%d\n", add(a, b));printf("减法结果:%d\n", subtract(a, b));printf("乘法结果:%d\n", multiply(a, b));printf("除法结果:%d\n", divide(a, b));return 0;
}

特别注意

需要注意的是,上述基于位运算模拟的四则运算代码示例只是简单的原理性实现,在实际应用中,可能需要更多的错误处理、边界情况考虑以及针对性能等方面进一步优化,实际应用中可能需要进一步完善代码来处理这些特殊情况。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/64733.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Spring] Spring AOP

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…

Java-数据结构-时间和空间复杂度

一、什么是时间和空间复杂度&#xff1f; &#x1f4da; 那么在了解时间复杂度和空间复杂度之前&#xff0c;我们先要知道为何有这两者的概念&#xff1a; 首先我们要先了解"算法"&#xff0c;在之前我们学习过关于"一维前缀和与差分"&#xff0c;"…

商汤C++开发面试题及参考答案

C++11 有哪些新特性? C++11 带来了众多令人瞩目的新特性,极大地丰富和增强了这门编程语言的功能与表现力。 首先是类型推导方面,引入了auto关键字。通过auto,编译器能够自动根据初始化表达式来推导出变量的类型,这在处理复杂的模板类型或者较长的类型声明时非常方便,能让…

Cesium 实战 27 - 三维视频融合(视频投影)

Cesium 实战 27 - 三维视频融合(视频投影) 核心代码完整代码在线示例在 Cesium 中有几种展示视频的方式,比如墙体使用视频材质,还有地面多边形使用视频材质,都可以实现视频功能。 但是随着摄像头和无人机的流行,需要视频和场景深度融合,简单的实现方式则不能满足需求。…

U盘格式化工具合集:6个免费的U盘格式化工具

在日常使用中&#xff0c;U盘可能会因为文件系统不兼容、数据损坏或使用需求发生改变而需要进行格式化。一个合适的格式化工具不仅可以清理存储空间&#xff0c;还能解决部分存储问题。本文为大家精选了6款免费的U盘格式化工具&#xff0c;并详细介绍它们的功能、使用方法、优缺…

如何使用AI工具cursor(内置ChatGPT 4o+claude-3.5)

⚠️温馨提示&#xff1a; 禁止商业用途&#xff0c;请支持正版&#xff0c;充值使用&#xff0c;尊重知识产权&#xff01; 免责声明&#xff1a; 1、本教程仅用于学习和研究使用&#xff0c;不得用于商业或非法行为。 2、请遵守Cursor的服务条款以及相关法律法规。 3、本…

Spring Boot的开发工具(DevTools)模块中的热更新特性导致的问题

问题&#xff1a; java.lang.ClassCastException: class cn.best.scholarflow.framework.system.domain.entity.SysUser cannot be cast to class cn.best.scholarflow.framework.system.domain.entity.SysUser (cn.best.scholarflow.framework.system.domain.…

异常与中断(上)

文章目录 一、异常与中断的概念引入与处理流程1.1 生活中的中断1.2 母亲如何处理中断1.3 ARM系统中异常与中断处理流程 二、ARM架构中异常与中断的处理2.1 处理流程2.2 cortex M3/M42.2.1 M3/M4的向量表2.2.2 M3/M4的异常/中断处理流程 2.3 cortex A72.3.1 A7的向量表2.3.2 A7的…

Zabbix 监控平台 添加监控目标主机

Zabbix监控平台是一个企业级开源解决方案&#xff0c;用于分布式系统监视和网络监视。它由Zabbix Server和可选组件Zabbix Agent组成&#xff0c;通过C/S模式&#xff08;客户端-服务器模型&#xff09;采集数据&#xff0c;并通过B/S模式&#xff08;浏览器-服务器模型&#x…

游戏关卡设计的常用模式

游戏关卡分为很多种&#xff0c;但常用的有固定套路&#xff0c;分为若干种类型。 关卡是主角与怪物、敌方战斗的场所&#xff0c;包括装饰物、通道。 单人游戏的关卡较小&#xff0c;偏线性&#xff1b; 联机/MMO的关卡较大&#xff0c;通道多&#xff0c;自由度高&#xf…

【容器化技术 Docker 与微服务部署】详解

容器化技术 Docker 与微服务部署 一、容器化技术概述 &#xff08;一&#xff09;概念 容器化技术是一种操作系统级别的虚拟化方法&#xff0c;它允许将应用程序及其依赖项&#xff08;如运行时环境、系统工具、库等&#xff09;打包成一个独立的、可移植的单元&#xff0c;这…

TypeScript 后端开发中的热重载编译处理

在一些除了nest框架外的一些其他nodejs框架中没有提供对ts编译和热重载&#xff0c;如果使用typescript我们需要自己进行配置。 方法一&#xff08;推荐&#xff09; 使用bun运行环境&#xff08;快&#xff09;。注&#xff1a;一些不是使用js&#xff0c;ts代码编写的第三方…

QT集成IntelRealSense双目摄像头3,3D显示

前两篇文章&#xff0c;介绍了如何继承intel realsense相机和opengl。 这里介绍如何给深度数据和色彩数据一块显示到opengl里面。 首先&#xff0c;需要了解深度数据和彩色数据是如何存储的。先说彩色数据。彩色图像一般都是RGB&#xff0c;也就是每个像素有三个字节&#xf…

Postman[4] 环境设置

作用&#xff1a;不同的环境可以定义不同的参数&#xff0c;在运行请求时可以根据自己的需求选择需要的环境 1.创建Environment 步骤&#xff1a; Environment-> ->命名->添加环境变量 2.使用Environment 步骤&#xff1a;Collection- >右上角选择需要的环境

【合并区间】

问题 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。 请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。示例 1&#xff1a; 输入&#xff1a;intervals …

SpringBoot_第二天

SpringBoot_第二天 学习目标 Mybatis整合&数据访问 使用SpringBoot开发企业项目时&#xff0c;持久层数据访问是前端页面数据展示的基础&#xff0c;SpringBoot支持市面上常见的关系库产品(Oracle,Mysql,SqlServer,DB2等)对应的相关持久层框架&#xff0c;当然除了对于关系…

SparseViT:基于稀疏编码Transformer的非语义中心、参数高效的图像篡改定位

摘要 https://arxiv.org/pdf/2412.14598 非语义特征或语义无关特征&#xff0c;与图像上下文无关但对图像篡改敏感&#xff0c;被认为是图像篡改定位&#xff08;IML&#xff09;的重要证据。由于无法获得人工标签&#xff0c;现有工作依赖于手工方法提取非语义特征。手工非语…

Redisson 分布式锁获取tryLock和lock的区别

问题 boolean isLock lock.tryLock(10, 30, TimeUnit.SECONDS); boolean isLock lock.lock(30, TimeUnit.SECONDS); boolean isLock lock.lock(); 三者的区别&#xff1f;&#xff1f; 这三个方法都是用于获取 Redisson 分布式锁的&#xff0c;但它们在获取锁的方式和行为…

【git】git生成rsa公钥的方法

git生成rsa公钥的方法 一&#xff0c;简介二&#xff0c;操作方法三&#xff0c;总结 一&#xff0c;简介 在工作的过程中&#xff0c;经常需要生成rsa的密钥&#xff0c;然后提供给别人&#xff0c;然后别人给你开通代码下载权限。本文介绍如何在本地生成rsa的密钥供参考。 …

Zookeeper模式安装Kafka(含常规、容器两种安装方式)

一、#创作灵感# 公司使用Kafka的软件项目较多&#xff0c;故写技术笔记巩固知识要点 二、软件环境 - Kafka 3.9.0 官方下载地址&#xff1a;Kafka 3.9.0 - ZooKeeper 3.9.3 官方下载地址&#xff1a;ZooKeeper 3.9.3 - Docker Desktop 4.37 容器图形化工具 官方下载地址…