JS实现大数字加减以及比较大小

JS整数的精度是Math.pow(2,53),大于 9007199254740992 (16位数)的可能会丢失精度。所以对于大数字加减和比较,可以将数字拆分成多个15位数字,进行加减或比较。

数字拆分

function getMidNum(str, start, len) {
	if (start + len > 0) {
		return +str.substr(start < 0 ? 0 : start, start < 0 ? start + len : len)
	} else {
		return 0
	}
}

数字相加

**
 * js分治算法实现大整数相加,算法复杂度为O(n/15)
 * 处理情况:正数 + 正数、负数+负数、负数+正数、正数+负数
 * @param {String} a
 * @param {String} b
 * @returns {String}
 */
export const bigNumAdd = (a, b) => {
	if (a[0] === '-' && b[0] === '-') {
		return '-' + bigNumAdd(a.substr(1), b.substr(1))
	} else if (a[0] === '-') {
		return bigNumSub(b, a.substr(1))
	} else if (b[0] === '-') {
		return bigNumSub(a, b.substr(1))
	}
	let res = ''
	let temp = 0

	let len1 = a.length
	let len2 = b.length
	let n = Math.ceil(Math.max(len1, len2) / 15)
	//分成多少段
	for (let i = 1; i < n + 1; i++) {
		let num1 = getMidNum(a, len1 - i * 15, 15)
		let num2 = getMidNum(b, len2 - i * 15, 15)
		//15位数字相加
		let strTemp = String(temp + num1 + num2)

		if (i !== n) {
			//异常1:处理000000000000000+整数的异常情况
			if (strTemp.length < 15) {
				strTemp = '0'.repeat(15 - strTemp.length) + strTemp
				res = strTemp + res
				temp = 0
				continue
			}
			//异常2:15位相加等于16位
			if (strTemp.length === 16) {
				res = strTemp.substr(1, 15) + res
				temp = 1
				continue
			}
		}
		//相加后的结果放入res前面
		res = strTemp + res
		temp = 0
	}
	return res
}

数字相减

/**
 * 大整数相减,处理 负数-负数、负数-正数、正数-负数的情况
 * @param {String} a
 * @param {String} b
 * @returns {String}
 */
export const bigNumSub = (a, b) => {
	if (a[0] === '-' && b[0] === '-') {
		return bigNumSub(b.substr(1), a.substr(1))
	} else if (a[0] === '-') {
		return '-' + bigNumAdd(a.substr(1), b)
	} else if (b[0] === '-') {
		return bigNumAdd(a, b.substr(1))
	}
	let symb = ''
	if (bigNumCompare(a, b) < 0) {
		symb = '-'
		let cache = a
		a = b
		b = cache
	}
	let res = ''
	let temp = 0

	let n = Math.ceil(a.length / 15)
	//分成多少段
	for (let i = 1; i < n + 1; i++) {
		let num1 = getMidNum(a, a.length - i * 15, 15)
		let num2 = getMidNum(b, b.length - i * 15, 15)
		//15位数字相减
		let tempNum = num1 - num2 - temp
		if (tempNum < 0) {
			temp = 1
			tempNum = 1000000000000000 + tempNum
		} else {
			temp = 0
		}
		let strTemp = String(tempNum)

		if (i !== n) {
			//异常1:处理000000000000000+整数的异常情况
			if (strTemp.length < 15) {
				strTemp = '0'.repeat(15 - strTemp.length) + strTemp
			}
		}
		//相加后的结果放入res前面
		res = strTemp + res
	}
	return symb + res
}

数字比较

/**
 * 比较两个大整数的大小,返回-1,0,1  a<b返回-1
 * @param {String} a
 * @param {String} b
 * @returns {number}
 */
export const bigNumCompare = (a, b) => {
	let back = 0
	let max = Math.ceil(Math.max(a.length, b.length) / 15)
	//分成多少段,从左边开始
	for (let i = max; i > 0; i--) {
		let num1 = getMidNum(a, a.length - i * 15, 15)
		let num2 = getMidNum(b, b.length - i * 15, 15)
		//15位数字相减
		let cur = num1 - num2
		if (cur < 0) {
			back = -1
			break
		} else if (cur > 0) {
			back = 1
			break
		}
	}
	return back
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值