位运算符实现 四则运算
#include "stdafx.h" #include <iostream> using namespace std; /* 位运算符实现 加 减 乘 除 */ //加法运算 int add(int a, int b) { return b==0 ? a : add(a^b, (a&b)<<1); } //补码中正数转负数的原理 int negative(int a) { return add(1, ~a); } //减法运算 int sub(int a, int b) { return add(a, negative(b)); } //判断正负 bool isNegative(int a) { return (a&INT_MIN)!=0; //INT_MIN只有最高位为1,其余位为0 } //仅用于正数的乘法 int multi_help(int a, int b) { int result = 0; while (b) { if(b&1) result = add(result,a); a <<= 1; b >>= 1; } return result; } //乘法 int multi(int a, int b) { if (isNegative(a)) { if (isNegative(b)) return multi_help(negative(a), negative(b)); else return negative(multi_help(negative(a), b)); } else { if (isNegative(b)) return negative(multi_help(a, negative(b))); else return multi_help(a, b); } } //仅计算正数除法 int div_help(int a, int b) { if(a<b) return 0; if(a==b) return 1; int result = 0; //第32位为符号位,所以从第31位开始 for (int i=30; i>=0; i--) { if( (a>>i) >= b) { result = add(result, 1<<i); a = sub(a, b<<i); } } return result; } //除法 int divide(int a, int b) { if(isNegative(a)) { if(isNegative(b)) return div_help(negative(a), negative(b)); else return negative(div_help(negative(a), b)); } else { if (isNegative(b)) return negative(div_help(a, negative(b))); else return div_help(a, b); } } int _tmain(int argc, _TCHAR* argv[]) { int a,b; a = -28; b = 7; cout<<"a+b = "<<add(a, b)<<"\n" <<"a-b = "<<sub(a, b)<<"\n" <<"a*b = "<<multi(a, b)<<"\n" <<"a/b = "<<divide(a, b) <<endl; return 0; }
关于位运算符,可以参考:http://hi.baidu.com/xiaoduo170/item/b5d2810ac5c4f931a3332a54?qq-pf-to=pcqq.c2c
一下内容来源于上面的网址!
2009-07-02 16:11 C++ 位操作符绪言 我注意到一些人好像对位操作符不太清楚,所以我决定写篇简单的指南,说明如何使用他们。 位简介 bits,你会问他们是什么呢? 其实,简单说,我们在电脑上处理各种工作都是由许多1和0完成的。我们在电脑上存储的所有数据都是用bits来表示的。一个byte是用8个bit表示的,一个WORD是用两个BYTE表示的,或者16个bit。一个DWORD是用两个WORD表示的,或者32个bit. 0 1 0 0 0 1 1 1 1 0 0 0 0 1 1 1 0 1 1 1 0 1 0 0 0 1 1 1 1 0 0 0 || | | | || |+- bit 31 | | | bit 0 -+| | | | | | +-- BYTE 3 -----+--- BYTE 2 ----+--- BYTE 1 ----+-- BYTE 0 -----+ | | | +----------- WORD 1 ------------+----------- WORD 0 ------------+ | | +--------------------------- DWORD -----------------------------+ 使用位操作符的美妙之处在于你可以把BYTE, WORD 或 DWORD 当成一个小型的数组或者结构。你可以使用位操作符检查单独的一个位的值,设置某一个或一组位的值。 十六进制和他们与bits的关系 使用bits时,很难只使用二元符号1或者0去表示每个数值。为了解决这个问题我们使用十六进制(基数是16)数。 十六进制使用四个二进制位来表示从0到15的数字,这些数字也是单个的十六进制阿拉伯数字所能表示的范围。由四个二进制位或一个BYTE的一半组成的组被称为一个元组。一个BYTE包含两个元组,所以我们可以使用两个十六进制阿拉伯数字来表示一个BYTE类型的值。 NIBBLE HEX VALUE ====== ========= 0000 0 0001 1 0010 2 0011 3 0100 4 0101 5 0110 6 0111 7 1000 8 1001 9 1010 A 1011 B 1100 C 1101 D 1110 E 1111 F 因此,我们可以像下面这样用一个BYTE来表示字母'r'(ASCII码是114): 0111 0010 binary 7 2 hexadecimal 我们可以把它写成'0x72'. 二进制操作符 有六个位操作符,他们是: & 与 | 或 ^ 异 ~ 按位求反 >> 右移 << 左移 & 与操作符 &操作符比较两个数,只有要比较的两个值的相应位都被设置(为1-译者注)时,返回的值相应位才被设置。这些比较位使用下面的表进行比较: 1 & 1 == 1 1 & 0 == 0 0 & 1 == 0 0 & 0 == 0 这个操作符理想的应用是建立一个掩码来检查某个位的值。假设我们有一个包含某些位标志的字节,我们想检查它的位4是否被设置(即是否被置1-译者注): BYTE b = 50; if ( b & 0x10 ) cout << "Bit four is set" << endl; else cout << "Bit four is clear" << endl; 这会发生如下的计算: 00110010 - b & 00010000 - & 0x10 ---------- 00010000 - result 因此我们知道位4被置1了。 | 操作符 | 操作符比较两个数,只有他们相应位中的一个或两个同时被设置时,返回值相应位就会被设置。这些比较位使用下面的表进行比较: 1 | 1 == 1 1 | 0 == 1 0 | 1 == 1 0 | 0 == 0 这个操作符的理想应用是确保某个位被设置。假设我们想某个值的位3一定被设置: BYTE b = 50; BYTE c = b | 0x04; cout << "c = " << c << endl; 这会发生如下的计算: 00110010 - b | 00000100 - | 0x04 ---------- 00110110 - result ^操作符 ^操作符比较两个数,只有这两个数的相应位标志不同时,返回数的相应位才会被设置。这些比较位使用下面的表进行比较: 1 ^ 1 == 0 1 ^ 0 == 1 0 ^ 1 == 1 0 ^ 0 == 0 这个操作符理想的应用是固定某些位: BYTE b = 50; cout << "b = " << b << endl; b = b ^ 0x18; cout << "b = " << b << endl; b = b ^ 0x18; cout << "b = " << b << endl; 这会发生如下的计算: 00110010 - b ^ 00011000 - ^ 0x18 ---------- 00101010 - result 00101010 - b ^ 00011000 - ^ 0x18 ---------- 00110010 - result ~操作符 ~操作符将一个数的各位置反,即1变为0,0变为1。这个操作符的一个理想应用是设定某些位为0,其他的位为1,而不管这个数据的大小。假设除了位0和位1,我们想把其他的位置1: BYTE b = ~0x03; cout << "b = " << b << endl; WORD w = ~0x03; cout << "w = " << w << endl; 这会发生如下的计算: 00000011 - 0x03 11111100 - ~0x03 b 0000000000000011 - 0x03 1111111111111100 - ~0x03 w 另一个理想的应用是,联合使用&操作符确保某些位一定被置0: BYTE b = 50; cout << "b = " << b << endl; BYTE c = b & ~0x10; cout << "c = " << c << endl; 这会发生如下的计算: 00110010 - b & 11101111 - ~0x10 ---------- 00100010 - result >>和<<操作符 >>(右移)和<<(左移)操作符按指定的位数移动位组。>>操作符将位组从高位向低位移。<<操作符将位组从低位向高位移。这两个操作符的一个应用是由于某些原因(如,检验MKEWPARAM, HIWORD, 和 LOWORD宏)需要对齐位组。 BYTE b = 12; cout << "b = " << b << endl; BYTE c = b << 2; cout << "c = " << c << endl; c = b >> 2; cout << "c = " << c << endl; 这会发生如下的计算: 00001100 - b 00110000 - b << 2 00000011 - b >> 2 位域 另一个可以使用位的有意思的事是使用位域。你可以使用位域在BYTE,WORD或DWORD内建立更小的结构。例如,假设我们想知道日期,但我们我想尽可能使用较少的内存。我们可以像下面这样建立数据结构: struct date_struct { BYTE day : 5, // 1 to 31 month : 4, // 1 to 12 year : 14; // 0 to 9999 } date; 在这个例子中,'日'占用了5个位,'月'占用了接下来的4位,同时'年'占用了接下来的14位。位24不用。如果我用整型定义每个域,这个结构将占用12字节。 |0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0| | | | | +------ year ---------------+ month +-- day --+ 现在,注意它的声明部分,看我们做了什么。 首先,我们看我们对位域结构使用的数据类型。这里我们用了BYTE。一个BYTE占8位,编译器将分配一个BYTE来存贮数据。如果在结构里我们使用了超过了8位的空间,编译器将分配另外的8位BYTE,直到能容纳我们的结构为止。如果我们使用了WORD或DWORD,编译器将分配一个总共32位的空间容纳我们的结构。 现在,我们来看下不同的域是怎样声明的。首先,我们使用冒号分开域名和位数。既然我们能获得位域的地址,我们就能使用这个结构的地址。 date.day = 12; dateptr = &date; dateptr->year = 1852;
Dreams are one of those things that keep you going and happy!!!