位运算的操作(加减乘除、负数、乘方、1的个数)

2023-05-16

一、位运算相关规律+口诀

c++中的位运算相关规律总结和口诀

二、加减乘除

int add(int num1, int num2){ 
	int temp;
    do {
    	temp = num1 ^ num2;//不进位相加:异或
    	num2 = (num1 & num2) << 1;//进位:位与+左移
    	num1 = temp;
    } while(num2!=0);
    return num1;
}
//num1为被减数,num2为减数
int substract(int num1, int num2){
    int subtractor = add(~num2, 1);//负数:取反加1
    int result = add(num1, subtractor);  
    return result ;
}
1、1110&1,最后1位=0,所以结果=0;被乘数1101左移1位=11010,乘数1110右移1位=0111;
2、0111&1,最后1位=1,所以结果=11010;被乘数11010左移1位=110100,乘数0111右移1位=0011;
3、0011&1,最后1位=1,所以结果=11010+110100=1001110;被乘数110100左移1位=1101000,乘数0011右移1位=0001;
4、0001&1,最后1位=1,所以结果=1001110+1101000=10110110;被乘数110100左移1位=11010000,乘数0011右移1位=0
乘数=0,循环结束。
(1) 判断乘数是否为0,为0跳转至步骤(4)
(2) 将乘数与1作与运算,确定末尾位为1还是为0,如果为1,则相加数为当前被乘数;如果为0,则相加数为0;将相加数加到最终结果中
(3) 被乘数左移一位,乘数右移一位;回到步骤(1)
(4) 确定符号位,输出结果;
//multiplicand被乘数,multiplier乘数,product乘积
int multiply(int a, int b) {  
    //将乘数和被乘数都取绝对值 
    int multiplicand = a < 0 ? add(~a, 1) : a;   
    int multiplier = b < 0 ? add(~b , 1) : b;  
     
    //计算绝对值的乘积  
    int product = 0;  
    while(multiplier > 0) {    
        if((multiplier & 0x1) > 0) {// 每次考察乘数的最后一位    
            product = add(product, multiplicand);    
        }     
        multiplicand = multiplicand << 1;// 每运算一次,被乘数要左移一位    
        multiplier = multiplier >> 1;// 每运算一次,乘数要右移一位(可对照上图理解)  
    }   
    //计算乘积的符号  
    if((a ^ b) < 0) {    
        product = add(~product, 1);  
    }   
    return product;
}

 

计算机是一个二元的世界,所有的int型数据都可以用[2^0, 21,...,231]这样一组基来表示(int型最高31位)。不难想到用除数的231,230,...,22,21,2^0倍尝试去减被除数,如果减得动,则把相应的倍数加到商中;如果减不动,则依次尝试更小的倍数。这样就可以快速逼近最终的结果。2的i次方其实就相当于左移i位,为什么从31位开始呢?因为int型数据最大值就是2^31

//dividend被除数,divisor除数,quotient商,remainder余数
int divide_v2(int a,int b) {   
    // 先取被除数和除数的绝对值    
    int dividend = a > 0 ? a : add(~a, 1);    
    int divisor = b > 0 ? a : add(~b, 1);    
    int quotient = 0;// 商    
    int remainder = 0;// 余数    
    for(int i = 31; i >= 0; i--) {
        //比较dividend是否大于divisor的(1<<i)次方,不要将dividend与(divisor<<i)比较,而是用(dividend>>i)与divisor比较,
        //效果一样,但是可以避免因(divisor<<i)操作可能导致的溢出,如果溢出则会可能dividend本身小于divisor,但是溢出导致dividend大于divisor       
        if((dividend >> i) >= divisor) {            
            quotient = add(quotient, 1 << i);            
            dividend = substract(dividend, divisor << i);        
        }    
    }    
    // 确定商的符号    
    if((a ^ b) < 0){
        // 如果除数和被除数异号,则商为负数        
        quotient = add(~quotient, 1);    
    }    
    // 确定余数符号    
    remainder = b > 0 ? dividend : add(~dividend, 1);    
    return quotient;// 返回商
}

三、判断整数number是否是2的乘方

bool isPower(int number) {
	return (number & number - 1) == 0;
}

四、判断正整数转换成二进制后的数字“1”的个数

//乘方:n&(n-1)可以把整数二进制的最右边的数由1变为0 
int bitCount1(int n) {
	int count = 0;
	while (n != 0) {
	    n = n & (n - 1);
	    count++;
	}
	return count;
}

//移位: 二进制与1进行&运算的时候,当最末位也就是最右边的一位为1的时候,结果就是1,
//判断完最后一位,然后把整数的二进制右移一位,再判断,直到整数等于 0 结束循环
int bitCount2(int n) {
	int count = 0;
	while (n > 0) {
	    if ((n & 1) == 1) count++;//如果最右边的值是1
	    n >>= 1; //向右一位
	}
	return count;
}

//可忽略。分治法,详见:https://www.jianshu.com/p/d8a0c6299dab
int bitCount3(int i) {
	i = i - ((i>>>1) & 0x55555555);
	i = (i & 0x33333333) + ((i>>>2)&0x33333333);
	i = (i+(i>>>4)) & 0x0f0f0f0f;
	i = i + (i>>>8);
	i = i + (i>>>16);
	return i & 0x3f;
}

转载:加减乘除

判断一个整数是否是2的乘方

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

位运算的操作(加减乘除、负数、乘方、1的个数) 的相关文章

  • c语言中四种简单的数组排序

    前言 本文介绍了几种c语言中对乱序数组的排序方式 具体的内容有 xff1a 插入排序 xff1b 冒泡排序 xff1b 选择排序 xff1b 希尔排序 xff1b 具体内容详见下文 一 插入排序 1 思路 首先假设数组的的前n位元素是有序的
  • 网桥的功能和分类

    br lan 61 lan 网桥 将WLAN和LAN 交换机 绑定为一个虚拟接口 连接两个局域网 xff0c 负责数据的中继和转发 交换机的前生 集线器 xff08 Hub xff09 是中继器的一种形式 xff0c 区别在于集线器能够提供
  • Java简介

    今天开始学习Java啦 xff0c 每天进步一点点 xff01 1 Java语言发展史 Java语言是美国Sun Stanford University Network 公司在1995年推出的计算机语言 xff0c java之父 xff1a
  • win10上WSL+vscode+xserver配置linux图形化程序开发环境

    受够了双系统来回切换 xff0c 尝试了一下wsl配置linux环境 xff08 个人习惯在linux上敲代码 xff09 xff0c 由于需求图形化 xff0c 又弄了xserver 没有装linux图形界面 WSL 安装按着官方的文档来
  • 02.Ubuntu 18.04安装KVM

    02 Ubuntu 18 04安装KVM 1 检查是否支持虚拟化 span class token function egrep span span class token parameter variable c span span cl
  • maven 打包缺失 resources 目录下的 jar 包,警告 jar should not point at files within the project directory

    报错如下 INFO Scanning for projects WARNING WARNING Some problems were encountered while building the effective model for co
  • Linux 下利用trash替换rm

    前言 rmtrash 是linux和mac下命令行版本rm的回收站 xff0c 安装后对用户透明 xff0c 符合正常使用rm的习惯 支持rm fr file哦 xff0c 有了他再也不怕rm时候手颤抖了 能自动拒绝 rm fr 哦 安装
  • 【异常】记一次前端因资源无法加载导致白屏异常问题

    一 背景 自从运维同事强烈要求前端的环境要使用多套的 xff0c 参考文章 项目 参考若依的前端框架去多环境 于是一番捣鼓与改造之后 xff0c 看似已经顺利了 但运维说 xff0c 前端还是有问题 xff0c 需要他帮我改下 xff0c
  • 三种方法实现后入先出的栈---leetcode题解225

    声明 xff1a 问题描述来源于leetcode 一 问题描述 xff1a 用队列实现栈 CategoryDifficultyLikesDislikesalgorithmsEasy 67 64 480 Tags stack design C
  • iOS|开发小技巧之UIView创建xib

    我们有的时候在创建UIView的时候 xff0c 想要使用xib进行创建视图发现 xff0c xib文件不能和UIView文件一起创建 所以 xff0c 我们要单独创建xib文件 我们选择Empty文件 xff0c 而不要选择View文件
  • PyCharm中安装Vim插件ideavim 并关闭vim编辑模式

    在PyCharm中安装Vim插件ideavim 进入File菜单下的Settings下的Plugins 搜索ideaVim 找到ideaVim插件 点击Install安装 重启并享受在Pycharm环境中使用Vim的乐趣 支持Vim三种模式
  • C++ typedef用法小结 (※不能不看※)

    第一 四个用途 用途一 xff1a 定义一种类型的别名 xff0c 而不只是简单的宏替换 可以用作同时声明指针型的多个对象 比如 xff1a char pa pb 这多数不符合我们的意图 xff0c 它只声明了一个指向字符变量的指针 xff
  • 中兴F450电信光猫改桥接模式

    前几天突然想搞外网访问 xff0c 但是电信这款光猫DMZ不能用让我很愁 xff0c 后来经过一番了解可以让光猫只负责光数转换 xff0c 剩下的事情交给路由 xff0c 但是要把光猫设置成桥接模式 这个光猫比较特殊不需要进入超级管理员只需
  • 群辉默认DDNS功能解析阿里云-自定义服务商

    前言 前不久买了个群辉NAS发现群辉DDNS不能解析阿里云 xff0c 后来找了很多教程都是部署Docker或使用其他平台转发一下 xff0c 然而这些平台还要注册 xff0c 我就在想我自己可不可以实现不需要注册就可以使用的DDNS xf
  • Debian 给非 ROOT 用户添加 sudoer 权限

    问题描述 从官方镜像安装的 Debian 9 xff08 Stretch xff09 比较纯净 xff0c 但因此需要自己安装 配置许多常用的 Linux 应用 xff0c 这里就需要 sudo xff08 super user do xf
  • ffmpeg Could not find codec parameters for stream

    在arm上使用ffmpeg rtmp拉流时出现了下面异常 xff1a flv 64 0x1b0e120 Could not find codec parameters for stream 2 Video h264 none 2560 kb
  • 五、Shell自动化脚本

    一键安装Nginx 脚本 install nginx sh span class token shebang important bin bash span span class token comment Use 使用Shell脚本一键安
  • Mysql数据库备份(一)------数据库备份和表备份

    一 Mysql中的数据备份 Mysql中数据备份使用的命令是 mysqldump 命令将数据库中的数据备份成一个文本文件 表的结构和表中的数据将存储在生成的文本文件中 mysqldump命令的 工作原理很简单 它先查出需要备份的表的结构 x
  • mysql如何查看自己数据库文件所在的位置

    本文详细讲解了如何查找mysql数据库真实物理文件的存储位置 xff0c 只要我们直接复制数据库文件 xff0c 即可对数据库进行搬迁 xff0c 也可以对数据库文件的存放位置进行改变 工具 原料 mysql数据库 方法 步骤 第1步 xf
  • MySQL开启SSL的利与弊

    最近 xff0c 准备升级一组MySQL到5 7版本 xff0c 在安装完MySQL5 7后 xff0c 在其data目录下发现多了很多 pem类型的文件 xff0c 然后通过查阅相关资料 xff0c 才知这些文件是MySQL5 7使用SS

随机推荐