T0 给定0-1之间double类型实数,给出他的二进制表示,32位之内无法表示输出ERROR
string s = "0.";
while(n != 0)
{
n *= 2;
if(n > 1)
{
s.append("1");
n -= 1;
}
else
s.append("0");
if(s.lenght() > 34)
{
cout<<"ERROR";
return 0;
}
}
cout<<s;
与&
T1 判断奇偶性,与1做&
T2 输出某整数二进制表示中1的个数
while(n != 0)
{
count++;
n = n & (n-1);
}
cout<<count;
T3 用一条语句判断某一整数是不是2的整数次方
if(n & (n-1) == 0)
cout<<"yes";
else
cout<"no:;
异或^
简单理解就是不进位加法,如1+1=0,,0+0=0,1+0=1。性质:
1、交换律
2、结合律(即(a^b)^c == a^(b^c))
3、对于任何数x,都有x^x=0,x^0=x
4、自反性 A XOR B XOR B = A xor 0 = A
简单例题
T1 交换两个整数变量的值,三次异或。注意:当两个指针变量指向同一个地址的数据时,只有传统写法可以工作。原因是异或写法直接在原地址上进行值运算,一次异或之后值就成了0,两个指针都指向这个地址,后面再怎么异或也只能是0。在应用中,如果要使用异或写法来交换元素,就得确保所传两个地址不一样,否则就会出现这话总错误。
a = a^b;b = a^b;a = a^b;
T2 不用判断语句求整数绝对值
b = (b^(b>>31)) - (b>>31);//^运算符的优先级低于- 补码!补码!补码!
T3 交换整数奇偶位
int out,even = 0xAAAAAAAA,odd = 0x55555555;
out = ((n & even) >> 1) ^ ((n & odd) << 1);
T4 找出重复一次的数,不使用辅助空间,每个数组元素只访问一次 (类似数组中数字都出现了偶数次,只有一个出现奇数次,找出奇数次的数)
//不用辅助空间 (数组内数字均在一定范围,如1~m,都有出现)
int ans = 0;
for(int i=1;i<=m;i++)
ans = ans ^ arr[i];
for(int j=0;j<n;j++)
{
ans = ans ^ arr[j];
}
cout<<ans;
//使用辅助空间,类似直方图 ,若没有说明数字范围,则不能异或,用此方法
int *helper = new int [n];
for(int i=0;i<n;i++)
{
helper[arr[i]]++;
}
for(int i=0;i<n;i++)
{
if(helper[i]==2)
{
cout<<endl<<i;
break;
}
}
delete []helper;
T5 位运算做加减乘除
//位运算实现加法
int addBit(int num1,int num2)
{
int sum,carry;
while(num2 != 0)
{
sum = num1 ^ num2;
//cout<<"sum = "<<sum<<endl;
carry = (num1 & num2)<<1;
//cout<<"carry = "<<carry<<endl;
num1 = sum;
num2 = carry;
}
return sum;
}
//位运算实现减法(实质仍为加法,数字在计算机中用补码存储,对数字进行求反加1即为该数字的相反数的补码表示)
int minusBit(int num1,int num2)
{
return addBit(num1,addBit(~num2,1));//-num2 = ~num2 + 1 = Add(~num2,1)
}
//位运算实现乘法
int multiplyBit(int num1,int num2)
{
if(num1 == 0 || num2 == 0)
return 0;
//先将被乘数与乘数全部弄为正数
int multiplicand = (num1 > 0)? num1 : addBit(~num1,1);
int multiplier = (num2 > 0)? num2 : addBit(~num2,1);
int res = 0;
while(multiplier > 0)
{
//如果最后一位是1,则进行加运算
if((multiplier & 0x1)== 1)
res = addBit(res,multiplicand);
//无论是否进行了加运算,都将被乘数左移一位,乘数右移一位
multiplicand <<= 1;
multiplier >>= 1;
}
//恢复符号,num1^num2为负值时表示两者异号,相乘必为负值
//(注意<优先级高于^,记得加括号)
if((num1 ^ num2) < 0)
return addBit(~res,1);
else
return res;
}
//位运算实现除法
int divideBit(int num1,int num2)
{
if(num1 == 0)
return 0;
if(num2 == 0)
return -1;
//先将被除数与除数全部弄为正数
int dividend = (num1 < 0) ? addBit(~num1,1) : num1;
int divisor = (num2 < 0) ? addBit(~num2,1) : num2;
int quotient = 0;
int remainder = 0;
//用除数的231, 230, …, 22, 21, 20倍尝试去减被除数(31,30……,2,1,0为上标)
for(int i=31;i>=0;i--)
{
//注意这里的dividend与divider比较,是将dividend右移i位而不是将divider左移i位
//目的在于避免divider左移i位后有些数据丢帧
if((dividend >> i) >= divisor)
{
//如果(dividend >> i) >= divider,表示dividend除divide的值大于1<<i,则将1左移i位并加入到商中
//此时表示从dividend中减去了1<<i个divide,所以dividend的值也跟着更新
quotient = addBit(quotient,1<<i);
dividend = minusBit(dividend,divisor<<i);
}
}
//余数符号
remainder = (num1 < 0) ? addBit(~dividend,1) : dividend;
//恢复商符号
if((num1 ^ num2) < 0)
{
quotient = addBit(~quotient,1);
}
cout<<"商:"<<quotient<<"\t";
cout<<"余数:"<<remainder<<endl;
return quotient;
}