C++学习笔记-----用位运算实现加减乘除

2023-12-26 05:18

本文主要是介绍C++学习笔记-----用位运算实现加减乘除,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

数据在计算机内存中是以二进制存储的。
几种常用的位运算:

  • 与运算&: 对应位均为1时为1,其它为0。
  • 或运算|: 对应位均为0时为0,其它为1。
  • 异或运算^: 对应位不相同时为1,相同时为0.
  • 按位取反~: 每一位取反
  • 右移>>: 将二进制进行右移,低位丢掉,高位补零。
  • 左移<<: 将二进制进行左移,低位补零,高位丢掉。

加法

以0111 + 0101为例,观察异或运算和与运算的结果

0111 ^ 0101 = 0010; //结果的每一位等于对应位相加模二,刚好是不带进位的加法结果。
0111 & 0101 = 0101; //结果的1表示对应位相加为2,0表示对应位相加小于二,刚好是进位标识。

又因为进位是向高位进位,也就是说如果第二位是1,则表示在计算过程中要向第三位进位,所以可以将与运算结果左移一位后和异或运算的结果做加法。
代码如下:

int add(int a, int b)
{
    return (b == 0) ? a : add(a ^ b, (a & b) << 1);/*if(b == 0)return a;elsereturn add(a ^ b, (a & b) << 1);//异或结果 + 与运算结果左移一位*/
}

减法

减法和加法相同,减去一个数相当于加上这个数的相反数,所以完全可以利用加法操作,唯一需要做的就是求出被减数的相反数。
求相反数的方法:每一位取反,末位加一。
代码如下:

//求n的相反数
//~:按位取反
//add:加法操作,末位加一
int negtive(int n)
{return add(~n, 1);
}int subtraction(int a, int b)
{//加上被减数的相反数return add(a, negtive(b));
}

乘法

平时在笔算乘法数据都是十进制的,而抛去思维定势,把数看成是二进制,也可以进行笔算乘法,像这样
这里写图片描述

根据算式可以知道,对于a * b,每次只需要将a左移一位乘上b的对应位,然后同上一次的结果做加法即可。
也就意味着当b的对应位为1时,对a左移一位然后同上一次的结果做加法。
如果b的对应位为0,只对a左移一位。
当然,上述这些运算不包括符号位,所以两个操作数都需要先转换成正数,符号需要单独考虑。对于4个字节(32位整数)来说,获取符号位只需要取出第31位的值即可。

代码如下:

//取出符号位
int getSign(int n)
{return n >> 31;
}//求n的绝对值
int positive(int n)
{return (getSign(n) & 1) ? negtive(n) : n;
}int multiply(int a, int b)
{//如果两个数符号位不相容,则结果为负bool isNegtive = false;if(getSign(a) ^ getSign(b))isNegtive = true;a = positive(a);b = positive(b);int res = 0;while(b | 0){//当b的对应位是1时,才需要加aif(b & 1)res = add(res, a);a = a << 1; //a左移b = b >> 1; //b右移}return isNegtive == true ? negtive(res) : res;
}

除法

同乘法一样,除法也可以进行二进制笔算,以a / b为例,只有当a >= b时才可以上商,又因为是二进制,所以商每次只会多1,在每次上1之后a都要减去一次b。代码如下:

int divide(int a, int b)
{//被除数不能为0if(b == 0)throw std::runtime_error("Divided can't be zero...");bool isNegtive = false;if(getSign(a) ^ getSign(b))isNegtive = true;a = positive(a);b = positive(b);int res = 0;while(a >= b){res = add(res, 1);a = subtraction(a, b);}return beNegtive == true ? negtive(res) : res;
}

这篇关于C++学习笔记-----用位运算实现加减乘除的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/538234

相关文章

Java实现字节字符转bcd编码

《Java实现字节字符转bcd编码》BCD是一种将十进制数字编码为二进制的表示方式,常用于数字显示和存储,本文将介绍如何在Java中实现字节字符转BCD码的过程,需要的小伙伴可以了解下... 目录前言BCD码是什么Java实现字节转bcd编码方法补充总结前言BCD码(Binary-Coded Decima

SpringBoot全局域名替换的实现

《SpringBoot全局域名替换的实现》本文主要介绍了SpringBoot全局域名替换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录 项目结构⚙️ 配置文件application.yml️ 配置类AppProperties.Ja

Python实现批量CSV转Excel的高性能处理方案

《Python实现批量CSV转Excel的高性能处理方案》在日常办公中,我们经常需要将CSV格式的数据转换为Excel文件,本文将介绍一个基于Python的高性能解决方案,感兴趣的小伙伴可以跟随小编一... 目录一、场景需求二、技术方案三、核心代码四、批量处理方案五、性能优化六、使用示例完整代码七、小结一、

Java实现将HTML文件与字符串转换为图片

《Java实现将HTML文件与字符串转换为图片》在Java开发中,我们经常会遇到将HTML内容转换为图片的需求,本文小编就来和大家详细讲讲如何使用FreeSpire.DocforJava库来实现这一功... 目录前言核心实现:html 转图片完整代码场景 1:转换本地 HTML 文件为图片场景 2:转换 H

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

C#实现一键批量合并PDF文档

《C#实现一键批量合并PDF文档》这篇文章主要为大家详细介绍了如何使用C#实现一键批量合并PDF文档功能,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言效果展示功能实现1、添加文件2、文件分组(书签)3、定义页码范围4、自定义显示5、定义页面尺寸6、PDF批量合并7、其他方法

SpringBoot实现不同接口指定上传文件大小的具体步骤

《SpringBoot实现不同接口指定上传文件大小的具体步骤》:本文主要介绍在SpringBoot中通过自定义注解、AOP拦截和配置文件实现不同接口上传文件大小限制的方法,强调需设置全局阈值远大于... 目录一  springboot实现不同接口指定文件大小1.1 思路说明1.2 工程启动说明二 具体实施2

Python实现精确小数计算的完全指南

《Python实现精确小数计算的完全指南》在金融计算、科学实验和工程领域,浮点数精度问题一直是开发者面临的重大挑战,本文将深入解析Python精确小数计算技术体系,感兴趣的小伙伴可以了解一下... 目录引言:小数精度问题的核心挑战一、浮点数精度问题分析1.1 浮点数精度陷阱1.2 浮点数误差来源二、基础解决

Java实现在Word文档中添加文本水印和图片水印的操作指南

《Java实现在Word文档中添加文本水印和图片水印的操作指南》在当今数字时代,文档的自动化处理与安全防护变得尤为重要,无论是为了保护版权、推广品牌,还是为了在文档中加入特定的标识,为Word文档添加... 目录引言Spire.Doc for Java:高效Word文档处理的利器代码实战:使用Java为Wo