Converting large integer to 8 byte array in JavaScript - Stack Overflow

I'm trying to convert a large number into an 8 byte array in javascript.Here is an IMEI that I am

I'm trying to convert a large number into an 8 byte array in javascript.

Here is an IMEI that I am passing in: 45035997012373300

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

This ends up giving the byte array: 48,47,7,44,0,0,160,0. Converted back to a long, the value is 45035997012373296, which is 4 less than the correct value.

Any idea why this is and how I can fix it to serialize into the correct bytes?

I'm trying to convert a large number into an 8 byte array in javascript.

Here is an IMEI that I am passing in: 45035997012373300

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

This ends up giving the byte array: 48,47,7,44,0,0,160,0. Converted back to a long, the value is 45035997012373296, which is 4 less than the correct value.

Any idea why this is and how I can fix it to serialize into the correct bytes?

Share Improve this question edited Apr 20, 2012 at 21:50 Phrogz 304k113 gold badges667 silver badges757 bronze badges asked Apr 20, 2012 at 21:10 JustinJustin 18.3k38 gold badges136 silver badges207 bronze badges 6
  • 1 Heads up, value will be a global variable. – Elliot Bonneville Commented Apr 20, 2012 at 21:12
  • How are you converting back to a long? This works just fine, for instance: jsfiddle/zuqgJ – mellamokb Commented Apr 20, 2012 at 21:14
  • @Elliot - This is code within a function. – Justin Commented Apr 20, 2012 at 21:15
  • @mellamokb - The byte array gets passed via UDP to a .NET (C#) windows service, which deserializes it using the BitConverter class. – Justin Commented Apr 20, 2012 at 21:16
  • can you add the conversion back to the long? – Ryan Commented Apr 20, 2012 at 21:19
 |  Show 1 more ment

3 Answers 3

Reset to default 3

Since you are converting from decimal to bytes, dividing by 256 is an operation that is pretty easily simulated by splitting up a number in a string into parts. There are two mathematical rules that we can take advantage of.

  1. The right-most n digits of a decimal number can determine divisibility by 2^n.
  2. 10^n will always be divisible by 2^n.

Thus we can take the number and split off the right-most 8 digits to find the remainder (i.e., & 255), divide the right part by 256, and then also divide the left part of the number by 256 separately. The remainder from the left part can be shifted into the right part of the number (the right-most 8 digits) by the formula 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, where \ is integer division and q and r are quotient and remainder, respectively for n \ 256. This yields the following method to do integer division by 256 for strings of up to 23 digits (15 normal JS precision + 8 extra yielded by this method) in length:

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

Technically this could be implemented to divide an integer of any arbitrary size by 256, simply by recursively breaking the number into 8-digit parts and handling the division of each part separately using the same method.

Here is a working implementation that calculates the correct byte array for your example number (45035997012373300): http://jsfiddle/kkX2U/.

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

Your value and the largest JavaScript integer pared:

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

JavaScript cannot represent your original value exactly as an integer; that's why your script breaking it down gives you an inexact representation.

Related:

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

Edit: If you can express your number as a hexadecimal string:

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]

If you need the bytes ordered from least-to-most significant, throw a .reverse() on the result.

store the imei as a hex string (if you can), then parse the string in that manner, this way you can keep the precision when you build the array. I will be back with a PoC when i get home on my regular puter, if this question has not been answered.

something like:

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

or close to that whatever...

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744253905a4565300.html

相关推荐

  • Converting large integer to 8 byte array in JavaScript - Stack Overflow

    I'm trying to convert a large number into an 8 byte array in javascript.Here is an IMEI that I am

    8天前
    40

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信