1、常见的位运算使用场景
(1)移位运算(<<、>>):操作数的所有二进制位均左移相应位数,高位舍弃,低位补0,操作数的所有二进制位均右移相应位数,低位舍弃,高位补0或1:最高位为0补0,最高位为1补1。简单来说就是左移就是原数字乘2的n次方,右移就是原数字除2的n次方。
int n = 3; // 00000000 00000000 00000000 00000011 = 3
int n1 = n << 1; // 00000000 00000000 00000000 00000110 = 6 相当于3 × 2的1次方
int n2 = n << 2; // 00000000 00000000 00000000 00001100 = 12 相当于3 × 2的2次方
int n1 = n >> 1; // 00000000 00000000 00000000 00000001 = 1 相当于3 ÷ 2的1次方
(2)与运算(&):必须两个数字同时为1,结果才为1,若一个为1另一个为0或者同时为0则按结果为0处理。
int n = 123; // 01111011
int j = 115; // 01110011
int k = n & i; // 01110011 即结果为115
(3)或运算(|):二进制数字比对的两个数字中只要有一个数字为1,则结果就为1。若同时为0,则结果为0。
int n = 123; // 01111011
int j = 59; // 00111011
int k = n & i; // 01111011 即结果为123
(4)非运算(~):将二进制中的1转换为0,将0转换为1。
int n = 1234; // 0100 11010010
int n1 = ~n; // 1011 00101101
(5)异或运算(^):如果二进制数中的两个数不同,则结果为1,如果结果相同则为0。
int n = 123; // 01111011
int n1 = 139; // 10001011
int n2 = n ^ n1; // 11110000
2、整数类型运算时的类型溢出问题,产生原因以及解决办法。
(1)产生原因:
整数byte、short、int、long类型都存在范围限制,如果计算结果超出了范围,就会产生溢出。例如int类型中最大范围为-2^31 到 2^31-1,也就是 -2147483648 到 2147483647。当int类型的保存数值超过了最高值,结果占取了首高位,将原本的符号位改变成了1,因此造成负数的过程。
(2)解决方法:
- 将当前整数类型转换成更大范围的整数类型
- 用BigInteger引用类型来代表整数,可以更好的去计算超大类型的计算
- 在程序中设置限制条件、避免溢出异常报错。
3、浮点类型运算时的精度丢失问题,产生原因以及解决方法。
(1)产生原因:
浮点数有两种类型,float和double类型,计算机使用二进制存储数据,由于二进制自身局限性,在计算中小数是向上不断乘2取余,所以可能计算时会出现2进制小数部分无限循环的可能,导致其无法精确的表示所有小数。而浮点数是由整数部分和小数部分组成,这也就意味着,计算机无法精确表示浮点数。也有可能是使用的数字之间类型不匹配(例如,混合使用浮点型和双精度型)。
简单来说就是在计算浮点数时,计算开始循环,永远无法消除小数部分,根据精度不同会截取对应有效数字,所以小数的二进制有时候是不能精确的,就和我们十进制里不能准确表示1/3=0.33333333…是一个道理。
(2)解决方法:
- 使用BigDecimal类,用字符串的形式可以准确进行浮点数运算,不用担心精度丢失。
- 浮点型数据比较的时候不要用等号。例如:i - 10.0 <= 0.0000000001 这样就会减少点误差。
- 将结果的小数点后的数据四舍五入,保留两位小数。
- 转成整型再进行计算。