JavaScript 大数值(支持负数)位运算

       在js中对大数值的整数作异或、与等位运算时,如果直接使用操作符(^、&、>>>),得到的结果可能与预期不符。通常情况下是因为结果超过了js支持的整数范围(即从-2147483648到+2147483647),此时只能自定义位运算函数。

       总体思路是:把大数值转为二进制数组,每一位单独进行位运算,最后合并。

  1.  自定义异或函数
    function xor(a, b) {
    	// 没有超过js支持的整数范围(即从-2147483648到+2147483647),
    	// 则使用本身支持的异或运算
    	if((a>=-2147483648 && a<=2147483647) &&
    		(b>=-2147483648 && b<=2147483647)){
    		return a ^ b;
    	}
    	// 获取a和b的二进制数组
    	let x = toBinarys(a);
    	let y = toBinarys(b);
    	let isNe = false;
    	// 比较二进制运算的两个数字的大小,小的数字补齐
    	// 如果是负数,高位补齐1(因为是反码)
    	// 如果是正数,高位补齐0
    	if (x.length != y.length) {
    		if (x.length > y.length) {
    			let size = x.length - y.length;
    			for (let i = 0; i < size; i++) {
    				if(b<0){
    					y.unshift(1);
    				}else{
    					y.unshift(0);
    				}
    			}
    		} else {
    			let size = y.length - x.length;
    			for (let i = 0; i < size; i++) {
    				if(a<0){
    					x.unshift(1);
    				}else{
    					x.unshift(0);
    				}
    			}
    		}
    	}
    	let z = new Array();
    	let len = x.length > y.length ? x.length : y.length;
    	// 每一个做异或运算,最后合并为字符串
    	for (let i = 0; i < len; i++) {
    		z.push(x[i] ^ y[i]);
    	}
    	z = z.join("");
    	// 因为自带的parseInt转负数(补码)的时候,结果不对
    	// 使用自定义的函数
    	return parseIntWithNegative(z);
    }
  2.   自定义与函数
    function and(a, b){
    	a = Number.parseInt(a);
    	b = Number.parseInt(b);
    	if((a>=-2147483648 && a<=2147483647) &&
    		(b>=-2147483648 && b<=2147483647)){
    		return a & b;
    	}
    	let x = toBinarys(a);
    	let y = toBinarys(b);
    	if(x.length != y.length){
    		if(x.length > y.length){
    			let size = x.length-y.length;
    			for(let i=0; i<size; i++){
    				if(b<0){
    					y.unshift(1);
    				}else{
    					y.unshift(0);
    				}
    			}
    		}else{
    			let size = y.length-x.length;
    			for(let i=0; i<size; i++){
    				if(a<0){
    					x.unshift(1);
    				}else{
    					x.unshift(0);
    				}
    			}
    		}
    	}
    	let res = new Array();
    	let len = x.length > y.length ? x.length : y.length;
    	for(let i=0; i < len; i++){
    		res.push(x[i] & y[i]);
    	}
    	res = res.join("");
    	return parseIntWithNegative(res);
    }
  3. 整数转为二进制数组
    function toBinarys(a) {
    	a = Number.parseInt(a).toString(2);
    	let bytes = [];
    	var result = []; 
    	let firstChar = a.charAt(0);
    	if(firstChar == '-'){
    		for (let i = 0; i < a.length; i++){
    			let v = a.substr(i, 1);
    			if(i==0){
    				bytes.push(1);
    			}else{
    				bytes.push(v==0?1:0);
    			}
    		}
    		let res = parseInt(bytes.join(""), 2) + 1;
    		a = Number.parseInt(res).toString(2);
    	}else{
    		result.push(0);
    	}
    	for (let i = 0; i < a.length; i++){
    		result.push(a.substr(i, 1));
    	}
    	return result;
    }
  4. 自定义二进制字符串转十进制函数(支持负数)
    // 传入的是二进制字符串
    function parseIntWithNegative(ne){
    	let bytes = [];
    	let firstChar = ne.charAt(0);
    	//如果是负数,则补码减一,然后取反,就是原码了
    	// 然后调用parseInt(),前面加负号
    	if(firstChar == 1){
    		for (let i = 0; i < ne.length; i++){
    			bytes.push(ne.substr(i, 1));
    		}
    		for (let j = ne.length-1, x=ne.length-1; j >=0; j--){
    			let v = ne.substr(j, 1);
    			if(j==0){
    				break;
    			}
    			if(v==1){
    				bytes[j] = 0;
    				break;
    			}else{
    				bytes[j] = 1;
    			}
    		}
    		for (let k = 0; k < bytes.length; k++){
    			let v = bytes[k];
    			bytes[k] = (v==0?1:0);
    		}
    		let res = bytes.join("");
    		return '-' + parseInt(res, 2);
    	}
    	for (let i = 0; i < ne.length; i++){
    		bytes.push(ne.substr(i, 1));
    	}
    	let res = bytes.join("")
    	return parseInt(res, 2);
    	
    }
  5. 自定义无符号右移函数
    function rightShift(a, b){
    	a = Number.parseInt(a);
    	if((a>=-2147483648 && a<=2147483647)){
    		return a >>> b;
    	}
    	let x = toBinarys(a);
    	for(let i=0; i<b; i++){
    		x.pop();
    	}
    	x = x.join("");
    	return parseInt(x, 2);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值