繁体   English   中英

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

[英]Converting large integer to 8 byte array in JavaScript

我正在尝试将大量数字转换为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。

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

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

  1. 十进制数的最右边的n位数可以确定2 ^ n的可分性。
  2. 10 ^ n将始终可被2 ^ n整除。

因此,我们可以取数字并拆分最右边的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位数) 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 ,其中\\是整数除法, qr分别是n \\ 256商和余数。 这产生了以下方法:对于长度为23位的字符串(15个普通JS精度+此方法产生的8个额外字符串),整数除以256:

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();
    }
}

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

这是一个工作实现,为您的示例编号计算正确的字节数组( 45035997012373300 ): http//jsfiddle.net/kkX2U/

[52, 47, 7, 44, 0, 0, 160, 0]

您的值和最大的JavaScript整数比较:

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()

将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));
   }
}

或者接近那个......

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM