位操作实现加减乘除四则运算

常见的位操作实现

1. 常用的一个等式:-n = ~(n - 1) = ~n + 1

2. 获取整数的二进制的最右边的1:n & (-n) 或 n & ~(n - 1)。例如 n = 010100, -n = 101100,那么n & (-n) = 000100

3. 去除整数的二进制的最右边的1:n & (n - 1)。例如 n = 010100,n-1 = 010011,n&(n-1) = 010000

加法操作

实现加法操作使用”异或“和”与“来实现。对应位的异或操作可以得到该位的值,对应位的与操作可以产生该位对高位的进位值。

//加法
int BinaryAdd(int a, int b) {
	int carry, add;
	do {
		add = a ^ b; //该操作得到本位的加法结果
		carry = (a & b) << 1; //该操作得到该位对高位的进位值
		a = add;
		b = carry;
	} while (carry != 0); //循环直到某次运算没有进位,运算结束
	return add;
}

减法操作

减法操作可以用加法操作来实现。例如 a - b = a + (-b) = a + (~b + 1)

//减法
int BinarySub(int a, int b) {
	return BinaryAdd(a, BinaryAdd(~b, 1));
}

乘法操作

二进制的乘法与十进制原理类似:都是将乘数的每一位和被乘数的每一位依次相乘,然后将相乘的结果相加即可。

例如:

可以看出,乘法过程:如果乘数b的第i(i >= 1;i = 1是乘数最右侧的那一位)位为1,那么该位与被乘数a相乘的结果S[i]就是(a << i);然后将这些所有的结果S[i]相加即为最后结果。

/*乘法
该过程中的bit_map是为了快速得到乘法过程中某位相乘的中间结果S[i]
需要位移的位数。bit_map的键值是2^0, 2^1,2^2, ……之类的数,对应的
值是0,1,2,……(即需要位移的位数)。
*/
int BinaryMultiply(int a, int b) {
	bool neg = (b < 0);
	if(b < 0)
		b = -b;
	int sum = 0;
	map<int, int> bit_map;
	for(int i = 0; i < 32; i++) {
		bit_map.insert(pair<int, int>(1 << i, i));
	}

	while(b > 0) {
		/*
		b & ~(b - 1)可以得到乘数b的二进制表示中最右侧1的位置
		last_bit记录被乘数a需要位移的位数
		*/
		int last_bit = bit_map[b & ~(b - 1)];
		//将得到的乘法结果全部相加即为最后结果
		sum += (a << last_bit);
		b &= b - 1; //每次将b的二进制表示的最右侧1去掉用于下一次乘法
	}
	if(neg)
		sum = -sum;
	return sum;
}

除法操作

例如:求101011除以11:

在上图的除法过程中:

(1)第一次除法先找到除数应该左移的位数,使得除数是不大于除数的数,上图中将除数左移了三位(11<< 3 = 11000),变为11000;然后本次除法结果为(1 << 3);被除数变为了原来的被除数101011 减去当前的除数11000:10011,该被除数就是下一次除法的被除数。

(2)第二次除法的被除数为10011,此次的除数为上一次除法右移一位,即(原始除数11左移两位:11<<2 = 1100);本次除法结果为(1<<2);被除数变为10011 - 1100 = 111,这作为下一次除法的被除数。

(3)第三次除法的被除数变为111,除数是上一次除法右移一位,也就是初始除数11左移一位(11<< 1 = 110);本次除法结果为(1<<1);被除数为111 - 110  = 1;

(4)乘法结束。商为(1 << 3 + 1 << 2 + 1 << 1)   = 1000 + 100 + 10 = 1110 = 14。

代码如下:

//除法
int BinaryDivide(int a, int b){
	bool neg = (a > 0) ^ (b > 0);
	if(a < 0)
		a = -a;
	if(b < 0)
		b = -b;
	if(a < b)
		return 0;
	int msb = 0;
	//msd记录除数需要左移的位数
	for(msb = 0; msb < 32; msb++) {
		if((b << msb) >= a)
			break;
	}
	int q = 0; //记录每次除法的商
	for(int i = msb; i >= 0; i--) {
		if((b << i) > a)
			continue;
		q |= (1 << i);
		a -= (b << i);
	}
	if(neg)
		return -q;
	return q;
}

测试

int main() {
	int a, b;
	cin >> a >> b;
	cout << "和: " << BinaryAdd(a, b) << endl;
	cout << "差: " << BinarySub(a, b) << endl;
	cout << "积: " << BinaryMultiply(a, b) << endl;
	cout << "商: " << BinaryDivide(a, b) << endl;
}

时间: 2024-08-26 07:25:52

位操作实现加减乘除四则运算的相关文章

Java程序完成加减乘除四则运算

一.项目名称:加减乘除四则运算 二.设计思路: 1.在对话框中输入两个数,并转化为int类型 2.进行加减乘除四则运算 3.输出结果 三.流程图 四.源代码 import javax.swing.JOptionPane; public class SiZeYunSuan { public static void main(String[] args) { // TODO 自动生成的方法存根 int n1=Integer.parseInt(JOptionPane.showInputDialog("

大数运算实现加减乘除四则运算

首先,让我们先来熟悉一下两种防止头文件被重复引用的处理#pragma once和#ifndef的区别 http://10739786.blog.51cto.com/10729786/1730827 接下来,开始我们的主题 <大数运算>    在平时生活中细心的你可能会发现,好多时候我们使用计算器时,总有一个显示的最大值,当计算超过这个值时就不能再计算了,那如果我们想要计算更大的数值要怎么办? 本文通过C++编程实现 大数的加减乘除四则运算 <思路与方法同样都在程序内部> 这次通过标

Qt之加减乘除四则运算-支持负数

一.效果展示 如图1所示,是简单的四则运算测试效果,第一列为原始表达式,第二列为转换后的后缀表达式,冒号后为结果.表达式支持负数和空格,图中是使用了5组测试数据,测试结果可能不全,如大家发现算法有问题,可留言,谢谢. 图1 四则运算展示 二.一些小技巧 在网上找了很多四则运算帖子,讲的都挺不错,思路很清晰,可是很少有拿来直接能用的,并且大多数的都不支持负数运算,既然是四则运算当然需要支持负数运算了,在这里我们只需要使用一点儿小技巧即可. 1.针对负号进行字符串修复 例如:-1*-3+2*(3+3

Python基础算法综合:加减乘除四则运算方法

#!usr/bin/env python# -*- coding:utf-8 -*-#python的算法加减乘除用符号:+,-,*,/来表示#以下全是python2.x写法,3.x以上请在python(打印放入括号内) 例如:print('1+1=',1+1)print '*-----------------------------------------------------*分割符'print "1+1=",1+1 #打印加法1+1的结果2print "2-1=&quo

47 - 按位实现加减乘除 四则运算

不使用+-*/四则运算符,实现两个数的四则运算. 1. 加 用二进制位实现两个数之间的加法.不考虑2个数相加的和溢出问题. 如 9+15=24 1001 + 1111,由于二进制 0+0=0,1+0=1, 0+1=1, 1+1=0, 可以发现是异或运算,而产生进位,则只有1 ,1相加,即与运算. int add(int nums1, int nums2) { if (nums1 == 0 || nums2 == 0) return (nums1 == 0) ? nums2 : nums1; in

c++实现大数加减乘除四则运算

通过c++字符串string实现大数的加.减.乘.除 1 #include <iostream> 3 #include <cstdlib> 4 #include <vector> 6 #include <sstream> 7 #include <algorithm> 9 using namespace std; 10 11 class Solution { 12 public: 13 string addTwoString(string nums

高精度模板(含加减乘除四则运算)

高精度加高精度 1 void BigAddBig(char *a, char *b, char *c) 2 { 3 //a表示结果,b,c位加数 4 int a_int[1005] = { 0 }, b_int[1005] = { 0 }, c_int[1005] = { 0 }; 5 int len1, len2, len, i; 6 len1 = strlen(b); 7 len2 = strlen(c); 8 for (i = 0; i < len1; i++) 9 b_int[i] =

大整数的存储与加减乘除四则运算

当需要计算的整数或计算结果可能会超出long long 所能表示的范围时,应该用大整数来存储和计算(Java里面有BigInteger来存储大整数,这里讨论的是C++语言). 大整数的存储形式是下面这个结构体(包含了构造函数): // 大整数结构体 struct bign{ int d[1000]; int len; bign(){ memset(d, 0, sizeof(d)); len = 0; } }; 首先以字符串的形式读去数据,然后将字符串逐个逆序字符存入d[]数组(可以采用用reve

位操作的个人总结

在计算机中所有数据都是以二进制形式进行存储,而位运算就是直接对内存中的二进制数据进行操作,因此处理速度非常快. 1. 基本操作 运算符 用法示例 运算规则 按位与 AND a & b 只有两个操作数相应的比特位都为1时,结果才为1,否则为0 按位或 OR a | b 只有两个操作数相应的比特位都为0时,结果才为0,否则为1 按位异或 XOR a ^ b 两个操作数相应比特位不相同时,结果为1,否则为0 按位取反 NOT ~a 操作数相应比特位取反,0变为1, 1变为0 左移 a <<