[英]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是通过将字符串中的数字拆分为多个部分而非常容易模拟的操作。 我们可以利用两个数学规则。
因此,我们可以取数字并拆分最右边的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
,其中\\
是整数除法, q
和r
分别是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.