有时候,我们为了追求效率,或者某些场景下,可能针对运算方式进行调整
比如说,不同语言进行数据传输的时候,数据类型精度不匹配,如何尽量减少这种情况的发生
就需要使用到一些位运算的技巧了。
抛开语言层面,仅从逻辑出发即可,以下代码,都可以使用其他语言方式替换
/**
* 两数加法运算
* **/
const add = function (num1, num2) {
//进位运算为0则结束
if (num2 === 0) {
return num1;
}
//没有进位的运算 亦或操作,(两不相等则1)
let sum = num1 ^ num2;
//与操作,同1 则1,这时候使用左移一位的操作表示进位
let carry = (num1 & num2) << 1;
return this.add(sum, carry);
}
/**
* 两数减法运算
* 减法,简单的做法就是把减法看做是加法,(加一个负数)
* **/
const plus = function (num1, num2) {
//取反相加
let num3 = this.add(~num2, 1);
let result = this.add(num1, num3);
return result;
}
/**
* 两数乘法运算m * n
* 实际上就是将m进行n次相加运算,但是要考虑到负数的情况等
* 所以需要对负数进行取反处理
* **/
const multi = function (num1, num2) {
let a = num1 < 0 ? this.add(~num1, 1) : num1;
let b = num2 < 0 ? this.add(~num2, 1) : num2;
let result = 0;
while (b > 0) {
//取尾数,因为要累加
if ((b & 0x1) > 0) {
result = this.add(result, a);
}
//每次运算结束,被乘数进行一次左移运算,进位的操作
a = a << 1;
//乘数进行一次右移操作,表示要执行次数
b = b >> 1;
}
//亦或操作,两不相等则1,判断正负号,取最高位比较,如果为负数,则取反加一
if ((num1 ^ num2) < 0) {
result = this.add(~result, 1);
}
return result;
}
/**
* 两数除法运算
* 后续实现,目前仅用的到加法与乘法
* **/
const division = function (num1, num2) {
//可以想一想如何使用位运算实现除法的方式
}
/**
* java实现
* 两数除法运算
* @param decimals 保留几位小数,默认保留10位
* **/
public static Long divide(Long d1, Long d2, int decimals){
long a = d1 >> 63 == 1 ? add(~d1, 1L) : d1;
long b = d2 >> 63 == 1 ? add(~d2, 1L) : d2;
long result = 0;
// 余数
long remainder = 0;
//累加:整体表示,以双倍的加法计算,提升效率。(b & 0x1) > 0时候才累加一次;
while(a >= b){
result = add(result, 1L);
a = subtraction(a, b);
}
//判断符号位,异或操作,同位同值则0,否则1,;与负负得正,一负为负相同,故可根据亦或操作判断符号
if((d1 ^ d2) < 0){
result = add(~result, 1L);
}
//获取余数符号
remainder = d2 > 0 ? a : add(~a, 1L);
return result;
}