在JavaScript中将大整数转换为8字节数组

时间:2012-04-20 21:10:57

标签: javascript bytearray

我正在尝试将大量数字转换为javascript中的8字节数组。

这是我传递的IMEI:45035997012373300

var bytes = new Array(7);
for(var k=0;k<8;k++) {
  bytes[k] = value & (255);
  value = value / 256;
}

这最终给出了字节数组:48,47,7,44,0,0,160,0。转换回long,值为45035997012373296,比正确值小4。

知道为什么会这样,以及如何修复它以序列化到正确的字节?

3 个答案:

答案 0 :(得分:3)

由于您要从十进制转换为字节,因此除以256是一项非常容易模拟的操作,方法是将字符串中的数字拆分为多个部分。我们可以利用两个数学规则。

  1. 十进制数的最右边n位数可以确定2 ^ n的可分性。
  2. 10 ^ n将始终可被2 ^ n整除。
  3. 因此,我们可以取数字并拆分最右边的8位数来找到余数(即& 255),将右边的部分除以256,然后将数字的左边部分除以256分开。左边部分的余数可以通过公式n*10^8 \ 256 = (q*256+r)*10^8 \ 256 = q*256*10^8\256 + r*10^8\256 = q*10^8 + r*5^8移动到数字的右边部分(最右边的8位数),其中\是整数除法q和{ {1}}分别是r的商和余数。这产生了以下方法:对于长度为23位的字符串(15个普通JS精度+此方法产生的8个额外字符串),整数除以256:

    n \ 256

    从技术上讲,这可以实现将任意大小的整数除以256,只需递归地将数字分成8位数部分,并使用相同的方法分别处理每个部分的划分。

    这是一个工作实现,它为您的示例编号(function divide256(n) { if (n.length <= 8) { return (Math.floor(parseInt(n) / 256)).toString(); } else { var top = n.substring(0, n.length - 8); var bottom = n.substring(n.length - 8); var topVal = Math.floor(parseInt(top) / 256); var bottomVal = Math.floor(parseInt(bottom) / 256); var rem = (100000000 / 256) * (parseInt(top) % 256); bottomVal += rem; topVal += Math.floor(bottomVal / 100000000); // shift back possible carry bottomVal %= 100000000; if (topVal == 0) return bottomVal.toString(); else return topVal.toString() + bottomVal.toString(); } } )计算正确的字节数组:http://jsfiddle.net/kkX2U/

    45035997012373300

答案 1 :(得分:2)

您的价值与largest JavaScript integer比较:

45035997012373300  // Yours
 9007199254740992  // JavaScript's biggest integer

JavaScript无法将整个值完全表示为整数;这就是为什么你的脚本分解它会给你一个不精确的表示。

相关:

var diff = 45035997012373300 - 45035997012373298;
// 0 (not 2)

修改:如果您可以将数字表示为十六进制字符串:

function bytesFromHex(str,pad){
  if (str.length%2) str="0"+str;
  var bytes = str.match(/../g).map(function(s){
    return parseInt(s,16);
  });
  if (pad) for (var i=bytes.length;i<pad;++i) bytes.unshift(0);
  return bytes;
}

var imei = "a000002c072f34";
var bytes = bytesFromHex(imei,8);
// [0,160,0,0,44,7,47,52]

如果您需要从最小到最重要的顺序排列的字节,请在结果上抛出.reverse()

答案 2 :(得分:0)

将imei存储为十六进制字符串(如果可以的话),然后以这种方式解析字符串,这样就可以在构建数组时保持精度。如果这个问题没有得到解答,我将在常规计算机上回家时使用PoC回来。

类似的东西:

function parseHexString(str){
   for (var i=0, j=0; i<str.length; i+=2, j++){
      array[j] = parseInt("0x"+str.substr(i, 2));
   }
}

或接近那个......