【转】Scala的5种运算:位运算、算术运算、关系运算、逻辑运算、赋值运算

最近刷leetcode刷到位运算相关的,比如191. 位1的个数、 231. 2 的幂,所以这里补一下位运算相关的知识点。

看到一篇文章对于Scala的5种运算,  位运算、算术运算、关系运算、逻辑运算、赋值运算,写的很全面、详细,这里转载其中位运算的部分。有兴趣的同学可以去看原文。

原文: Scala(3) -- scala运算符 ,原作者:erainm

原文链接:https://blog.csdn.net/eraining/article/details/108681078


5. 位运算符

5.1 铺垫知识

要想学好 位运算符 , 你必须得知道三个知识点:

什么是进制
什么是8421码
整数的原码, 反码, 补码计算规则
5.1.1 关于进制

通俗的讲, 逢几进一就是几进制, 例如: 逢二进一就是二进制, 逢十进一就是十进制, 常用的进制有以下几种:

进制名称    数据组成规则    示例
二进制    数据以0b(大小写均可)开头, 由数字0和1组成    0b10001001,0b00101010
八进制    数据以0开头, 由数字0~7组成    064, 011
十进制    数据直接写即可, 无特殊开头, 由数字0~9组成    10, 20, 333
十六进制    数据以0x(大小写均可)开头, 由数字0~9, 字母A-F组成(大小写均可)    0x123F, 0x66ABC
注意:
关于二进制的数据, 最前边的那一位叫: 符号位, 0表示正数, 1表示负数. 其他位叫: 数值位.
例如: 0b10001001 结果就是一个: 负数, 0b00101010 结果就是一个: 正数.
5.1.2 关于8421码

8421码就是用来描述 二进制位和十进制数据之间的关系的 , 它可以帮助我们快速的计算数据的二进制或十进制形式.
8421码对应关系如下:

二进制位    0 0 0 0 0 0 0 0
对应的十进制数据    128 64 32 16 8 4 2 1

注意:

计算规则: 二进制位从右往左数, 每多一位, 对应的十进制数据 乘以2.
二进制和十进制相互转换的小技巧:
二进制转十进制: 获取该二进制位对应的十进制数据, 然后累加即可.
例如: 0b101对应的十进制数据计算步骤: 4 + 0 + 1 = 5
十进制转二进制: 对十进制数据进行拆解, 看哪些数字相加等于它, 然后标记成二进制即可.
例如: 10 对应的二进制数据计算步骤: 10 = 8 + 2 = 0b1010
5.1.3 关于整数的原反补码计算规则

所谓的原反补码, 其实指的都是二进制数据, 把十进制的数据转成其对应的二进制数据, 该二进制数据即为: 原码.

注意: 计算机底层存储, 操作和运算数据, 都是采用 数据的二进制补码形式 来实现的.
正数
正数的原码 , 反码, 补码都一样, 不需要特殊计算.
负数
负数的反码计算规则 : 原码的符号位不变, 数值位按位取反(以前为0现在为1, 以前为1现在为0)
负数的补码计算规则 : 反码 + 1

5.2 概述

位运算符指的就是 按照位 (Bit)来快速操作数据值 , 它只针对于整型数据. 因为计算机底层存储, 操作, 运算采用的都是数据的二进制补码形式, 且以后我们要经常和海量的数据打交道, 为了提高计算效率, 我们就可以使用位运算符来实现快速修改数据值的操作.

5.3 分类

运算符    功能解释
&    按位与, 规则: 有0则0, 都为1则为1.
|    按位或, 规则: 有1则1, 都为0则为0.
^    按位异或, 规则: 相同为0, 不同为1.
~    按位取反, 规则: 0变1, 1变0.
<<    按位左移, 规则: 每左移一位, 相当于该数据乘2, 例如: 2 << 1, 结果为4
>>    按位右移, 规则: 每右移一位, 相当于该数据除2, 例如: 6 >> 1, 结果为3

注意:
位运算符只针对于整型数据.
运算符操作的是数据的二进制补码形式.
小技巧: 一个数字被同一个数字位异或两次, 该数字值不变. 即: 10 ^ 20 ^20, 结果还是10
5.4 代码示例

// 定义两个变量a和b, 初始化值分别为: 3, 5
val a = 3 //二进制数据: 0000 0011
val b = 5 //二进制数据: 0000 0101
//结果为: 0000 0001, 转化成十进制, 结果为: 1
println(a & b) //打印结果为: 1
//结果为: 0000 0111, 转化成十进制, 结果为: 7
println(a | b) //打印结果为: 7
//结果为: 0000 0110, 转换成十进制, 结果为: 6
println(a ^ b) //打印结果为: 6
//计算流程: 1111 1100(补码) -> 1111 1011(反码) -> 1000 0100(原码) -> 十进制数据: -4
println(~ a) //打印结果为: -4
//计算流程: 1000 0011(-3原码) -> 1111 1100(-3反码) -> 1111 1101(-3补码) -> 0000 0010(取反后
新补码) -> 十进制数据: 2
println(~ -3) //打印结果为: 2
//计算流程: 0000 0011(3的补码) -> 0000 1100(新的补码) -> 十进制数据: 12
println(a << 2) //打印结果为: 12
//计算流程: 0000 0011(3的补码) -> 0000 0001(新的补码) -> 十进制数据: 1
println(a >> 1) //打印结果为: 1
println(a ^ b ^ b) //打印结果为: 3

6. 案例: 交换两个变量的值

6.1 需求

已知有两个Int类型的变量a和b, 初始化值分别为10和20, 请写代码实现变量a和变量b的值的交换.
即最终结果为: a=20, b=10.
注意: 不允许直接写 a=20, b=10 这种代码.

6.2 参考代码

方式一 : 通过算术运算符实现.

// 定义两个Int类型的变量a和b, 初始化值分别为10和20
var a = 10
var b = 20
//将变量a和b的计算结果赋值给变量a
a = a + b //a = 30, b = 20
//计算并赋值
b = a - b //a = 30, b = 10
a = a - b //a = 20, b = 10
//打印结果
println("a: " + a) //a: 20
println("b: " + b) //b: 10

方式二 : 通过定义临时变量实现

// 定义两个Int类型的变量a和b, 初始化值分别为10和20
var a = 10
var b = 20
//定义临时变量temp, 记录变量a的值
var temp = a //a = 10, b = 20, temp = 10
//把变量b的值赋值给a
a = b //a = 20, b = 20, temp = 10
//把临时变量temp的值赋值给b
b = temp //a = 20, b = 10, temp = 10
//打印结果
println("a: " + a) //a: 20
println("b: " + b) //b: 10

方式三 : 通过位运算符实现

// 定义两个Int类型的变量a和b, 初始化值分别为10和20
var a = 10
var b = 20
//定义临时变量temp, 记录变量a和b的位异或值(这个值不需要我们计算)
var temp = a ^ b //即: temp = 10 ^ 20
//通过位异或进行交换变量值
a = a ^ temp //运算流程: a = a ^ temp = a ^ a ^ b = 10 ^ 10 ^ 20 = 20
b = b ^ temp //运算流程: b = b ^ temp = b ^ a ^ b = 20 ^ 10 ^ 20 = 10
//打印结果
println("a: " + a) //a: 20
println("b: " + b) //b: 10


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值