在JavaScript中,我有两个变量,每个变量包含一个十六进制数字作为字符串。 E.g:
var a = 'a3bc',
b = '1d0f';
现在我想添加它们(因此,结果应该是'c0cb'
)。为了让事情变得更容易,让我们对此进行一些约束:
0
为前缀,因此它会'001a'
,而不只是'1a'
。另一方面,有一些限制会使事情变得更难:
number
类型,这些数字太大了(这就是为什么this answer不起作用的原因。)'ffff'
和'0001'
,则结果应为'0000'
,而不是'10000'
。换句话说:所有计算都必须使用模除法。我目前有一个算法可以解决所有这些问题,但它很冗长,效率不高,而且一切都很优雅。它的想法是逐个字符地处理字符串,将它们转换为十进制,添加它们,将它们转换回来,记住潜在的溢出,等等。如上所述,它运作完美,但我认为它不是最好的解决方案。
我怎样才能以更好的方式解决这个问题?
PS:我需要在Node.js中这样做,所以如果有一个现成的模块可以做到这一点,我完全可以这样做: - )
答案 0 :(得分:2)
在最简单的情况下,您可以一次添加一个数字,跟踪进位:
var ndigits = 4, i, carry = 0, d, result = "";
for (i = ndigits - 1; i >= 0; i--) {
d = parseInt(a[i], 16) + parseInt(b[i], 16) + carry;
carry = d >> 4;
result = (d & 15).toString(16) + result;
}
如果性能是一个问题,您可能更喜欢一次处理多个数字,但事情变得困难或者您必须硬编码位数。即使这样,零填充的东西也需要一些工作。这是一个解决方案,它分三步执行20个十六进制数字,因此没有数字超过32位长:
function pad(s, n) { while (s.length < n) s = "0" + s; return s; }
d = parseInt(a.substr(13), 16) + parseInt(b.substr(13), 16);
result = pad((d & 0xfffffff).toString(16), 7);
d = parseInt(a.substr(6, 7), 16) + parseInt(b.substr(6, 7), 16) + (d >> 28);
result = pad((d & 0xfffffff).toString(16), 7) + result;
d = parseInt(a.substr(0, 6), 16) + parseInt(b.substr(0, 6), 16) + (d >> 28);
result = pad((d & 0xffffff).toString(16), 6) + result;
根据jsPerf,此代码似乎比上述代码快三倍,至少在某些浏览器上是这样。
答案 1 :(得分:0)
很高兴看到你已经拥有但你可以使用像BigNumber这样的任意算术库。
的Javascript
require.config({
paths: {
bignumber: 'https://raw.githubusercontent.com/MikeMcl/bignumber.js/master/bignumber.min'
}
});
require(['bignumber'], function (BigNumber) {
function sumHex() {
var args = [].slice.call(arguments),
length = args.length,
sum = new BigNumber(0, 16),
index;
for (index = 0; index < length; index += 1) {
sum = sum.plus(args[index], 16).mod('100000000000000000000', 16);
}
sum = sum.toString(16);
while (sum.length < 20) {
sum = '0' + sum;
}
return sum;
}
var a = '0000000000000000a3bc',
b = '00000000000000001d0f';
console.log(sumHex(a, b));
a = 'ffffffffffffffffffff';
b = '00000000000000000001';
console.log(sumHex(a, b));
});
输出
0000000000000000c0cb
00000000000000000000
上