我正在尝试将大量数字转换为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。
知道为什么会这样,以及如何修复它以序列化到正确的字节?
答案 0 :(得分:3)
由于您要从十进制转换为字节,因此除以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位数),其中\
是整数除法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));
}
}
或接近那个......