计算机基础-进制计算

1.首先先列一下所有的位运算符

1):按位与(&)
两个都位一才为1,例如5与8的与运算

0000 0101
&
0000 1000
——————
0000 0000

2): 按为或( | )
有1即为1,还是5与8的例子

0000 0101
|
0000 1000
——————
0000 1101

3):按位异或(^)
相同为0,不同为1,例子12 和 7

0000 1100
^
0000 0111
——————
0000 1011

4):按位取反( ~ )

5):左移运算<<(无符号左移<<<)

左移运算将数对应的二进位全部向左移动若干位,高位丢弃,低位补 0。左移运算的运算符为 <<。举个例子,将数字 5 左移 4 位,其实是将数字 5 对应的二进制 0000 0101 中的二进位向左移动 4 位

5 << 4
= 0000 0101 << 4
= 0101 0000 # 高位丢弃,低位补 0
= 80
=5*2的4次方

6)右移运算>> (无符号右移>>>,左边空缺补充为0)
右移运算将数对应的二进位全部向右移动若干位。对于左边的空位,如果是正数则补 0,负数可能补 0 或 1 (Turbo C 和很多编译器选择补 1)。右移运算的运算符为 >>。举个例子,将数字 80 右移 4 位,其实是将数字 80 对应的二进制 0101 0000 中的二进位向右移动 4 位,即:

80 >> 4
= 0101 0000 >> 4
= 0000 0101 # 正数补0,负数补1
= 5

2. 进制的相互转化

比如0.65换算成二进制就是:

0.65 × 2 = 1.3 取1,留下0.3继续乘二取整

0.3 × 2 = 0.6 取0, 留下0.6继续乘二取整

0.6 × 2 = 1.2 取1,留下0.2继续乘二取整

0.2 × 2 = 0.4 取0, 留下0.4继续乘二取整

0.4 × 2 = 0.8 取0, 留下0.8继续乘二取整

0.8 × 2 = 1.6 取1, 留下0.6继续乘二取整

0.6 × 2 = 1.2 取1,留下0.2继续乘二取整

3. 位运算常见用途

1. 使用异或交换进行变量交换

int a = 3, b = 5;
printf(“交换前:a=%d , b=%d\n”,a,b);
a = a^b;
b = a^b;
a = a^b;
printf(“交换后:a=%d , b=%d\n”,a, b);

2. 经典题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

  • 关键思路:
    1). 将所有的数异或一遍,剩下的数肯定是那两个只出现一次的数字的异或。
    2).当你得到最终异或的数,通过找到异或数字的二进制种第一个1的位置,可以把整个数组分成两部分,每一部分都各自拥有一个只出现一次的数字,按照第一步的方法,分别把每组不同的哪个数字找出来即可。
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        //找出两个特殊数字异或的数
        int target=0;
        for(int i=0;i<array.length;i++){
            target^=array[i];
        }
        int index=findFrist(target);
        for(int i=0;i<array.length;i++){
            //通过if分组,然后再异或从每组中获取那个特殊的值
            if(((array[i]>>index)&1)==0)
                num1[0]^=array[i];
            else
                num2[0]^=array[i];
        }
        
        
    }
    //找出异或的数中的二进制第一个1.
    int findFrist(int target){
        int index=0;
        while((target&1)==0&&index<32){
            target>>=1;
            index++;
        }
        return index;
    }
  1. 题目:求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
  • 思路:使用快速幂来计算
  • 快速幂:在这里插入图片描述

待解决。

  1. 题目:
    写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号
  • 思路:首先看十进制是如何做的: 5+7=12,三步走
    第一步:相加各位的值,不算进位,得到2。
    第二步:计算进位值,得到10. 如果这一步的进位值为0,那么第一步得到的值就是最终结果。
    第三步:重复上述两步,只是相加的值变成上述两步的得到的结果2和10,得到12。
    同样我们可以用三步走的方式计算二进制值相加: 5-101,7-111 第一步:相加各位的值,不算进位,得到010,二进制每位相加就相当于各位做异或操作,101^111。
    第二步:计算进位值,得到1010,相当于各位做与操作得到101,再向左移一位得到1010,(101&111)<<1。
    第三步重复上述两步, 各位相加 010^1010=1000,进位值为100=(010&1010)<<1。
    继续重复上述两步:1000^100 = 1100,进位值为0,跳出循环,1100为最终结果。
public class Solution {
    public int Add(int num1,int num2) {
       /*
       我们先来看一下十进制使怎么写的,首先,5+7,满十进一位,剩余的还在原位,
       然后我们再算满多少个10,进多少位,
       二进制也是一样,
       1. 首先,我们先算不用进一位的数,使用异或操作(不同为1)因为只有0和1,所以为1证明这一位既不需要进,也不没有值
       2. 接着,我们使用算需要金一位的数,使用&操作(都1才为1),然后将这些数左移一位,即是所有的进位数,
       3. 接着再将左移后的数,再次与第一步的结果,比较,直到第二步,也就是不需要进位数了就结束循环
        */
        while(num2!=0){
            int temp=num1^num2;
            num2=(num1&num2)<<1;
            num1=temp;
        }
        return num1;
    }
    
    
}
  1. 如何使用左移表示乘10;

res<<1+res<<3=22+28=2*10;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值