4

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少ない値です。

これがなぜであり、正しいバイトにシリアル化するように修正する方法はありますか?

4

3 に答える 3

3

10進数からバイトに変換しているので、256で除算することは、文字列内の数値を部分に分割することで非常に簡単にシミュレートできる操作です。利用できる数学的規則は2つあります。

  1. 10進数の右端のn桁は、2^nで除算可能性を決定できます。
  2. 10^nは常に2^nで割り切れます。

したがって、数値を取得し、右端の8桁を除算して余り(つまり、& 255)を見つけ、右側を256で除算してから、数値の左側を256で個別に除算することができます。左の部分の余りは、式によって数値の右の部分(右端の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桁の文字列(通常のJS精度15 +このメソッドによって生成される追加の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]
于 2012-04-20T21:52:46.080 に答える
2

あなたの値と比較された最大のJavaScript整数:

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

JavaScriptは、元の値を整数として正確に表すことはできません。そのため、スクリプトを分解すると、不正確な表現になります。

関連している:

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

編集:数値を16進文字列として表現できる場合:

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()、結果にをスローします。

于 2012-04-20T21:15:05.277 に答える
0

imeiを16進文字列として保存し(可能な場合)、その方法で文字列を解析します。これにより、配列を作成するときに精度を維持できます。この質問に回答がない場合は、通常のコンピューターで家に帰ったときにPoCで戻ってきます。

何かのようなもの:

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

またはそれに近いものは何でも...

于 2012-04-20T21:44:25.887 に答える