2011-12-12 156 views
22
function intFromBytes(x){ 
    var val = 0; 
    for (var i = 0; i < x.length; ++i) {   
     val += x[i];   
     if (i < x.length-1) { 
      val = val << 8; 
     } 
    } 
    return val; 
} 

function getInt64Bytes(x){ 
    var bytes = []; 
    var i = 8; 
    do { 
    bytes[--i] = x & (255); 
    x = x>>8; 
    } while (i) 
    return bytes; 
} 

我想轉換成一個字節數組,然後回到一個數字的JavaScript數字。但是,上述功能會產生大量不正確的輸出。轉換JavaScript整數到字節數組,並返回

var array = getInt64Bytes(23423423);  
var value = intFromBytes(array); 

console.log(value); //Prints 23423423 - correct 

var array = getInt64Bytes(45035996273704); 
var value = intFromBytes(array); 

console.log(value); //Prints -1030792152 - incorrect 

這是我的理解,JavaScript浮動53位,所以它不應該溢出?警報(Math.pow(2,53))正常工作。

+5

位移位總是上簽字,32位整數進行。 – Crozin

+0

這是有道理的,讓它成爲答案,我會接受。謝謝 –

+0

那麼解決方法是什麼? – Justin

回答

9

JavaScript位移(>>,<<)始終在帶符號的32位整數上執行。這導致大量的範圍溢出。

+1

但是如果需要long(64位有符號整數),那麼解決方案是什麼? –

+0

JS不支持64位長整數。看到這個:http://stackoverflow.com/questions/9643626/javascript-cant-handle-64-bit-integers-can-it和http://stackoverflow.com/questions/5353388/javascript-parsing-int64 – Crozin

+0

@ TimoKähkönen'x << y === x *(2 ** y)'右邊的解決方案可以用於64位整數。 – 2017-06-04 01:40:33

2

執行位移與2 ^(位數+1)相乘是相同的,因此,您不必移位位val = val<<8,而只需執行val = val*256。看看是否有效。

30

使用Susanoh13提供的提示,這裏有兩個功能,讓數轉換自/至的ByteArray:

longToByteArray = function(/*long*/long) { 
    // we want to represent the input as a 8-bytes array 
    var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]; 

    for (var index = 0; index < byteArray.length; index ++) { 
     var byte = long & 0xff; 
     byteArray [ index ] = byte; 
     long = (long - byte)/256 ; 
    } 

    return byteArray; 
}; 

byteArrayToLong = function(/*byte[]*/byteArray) { 
    var value = 0; 
    for (var i = byteArray.length - 1; i >= 0; i--) { 
     value = (value * 256) + byteArray[i]; 
    } 

    return value; 
}; 
+1

有時在byteArrayToLong()中,byteArray [i]被視爲字符串(依賴於瀏​​覽器),結果值計算錯誤。我已經通過* 1解決了:value =(value * 256)+ byteArray [i] * 1; – DrArt

+0

您應該指定是否將字節視爲包含有符號或無符號整數。 –

1

Brainfuck式Lodash版本。只是4 lulz!不要使用它!

const uintToArray = (uint, size) => _.chunk(_.padStart(uint, size*2, 0).split(''), 2).map((a)=>parseInt(a[0]+a[1])) 
0
<html> 
<head> 
    <meta charset="utf-8"> 
    <title>Uint32_To_Byte_Array</title> 
    <script> 
    function body_Add(Msg) 
    { 
     document.body.innerHTML = document.body.innerHTML + Msg; 
    } 
    class Byte 
    { 
     constructor(Value) 
     { 
      this.Number = new Uint8Array(1); 
      this.Number[0] = Value; 
     } 
     get Get() 
     { 
      return this.Number[0]; 
     } 
     set Set(newValue) 
     { 
      this.Number[0] = newValue; 
     } 
    }; 
    class Uint32 
    { 
     constructor(Value) 
     { 
      this.Number = new Uint32Array(1); 
      this.Number[0] = Value; 
     } 
     get Get() 
     { 
      return this.Number[0]; 
     } 
     set Set(newValue) 
     { 
      this.Number[0] = newValue; 
     } 
    }; 
    var Conversion = 
    { 
     Uint32_To_Byte_Array: function(Source_Num) 
     { 
      var Uint32_Num = new Uint32(Source_Num); 
      var Byte_Num = new Byte(0); 
      var Byte_Arr = new Uint8Array(4); 
      for (var i = 0; i < 4; i++) 
      { 
       if (Source_Num > 255) 
       { 
        Uint32_Num.Set = Source_Num/256; 
        Byte_Num.Set = Source_Num - Uint32_Num.Get * 256; 
       } 
       else 
       { 
        Byte_Num.Set = Uint32_Num.Get; 
        Uint32_Num.Set = 0; 
       } 
       Byte_Arr[i] = Byte_Num.Get; 
       Source_Num = Uint32_Num.Get; 
      } 
      return(Byte_Arr); 
     }, 
     Byte_Array_To_Uint32: function(Source_Byte_Array, Start_Position) 
     { 
      var Uint32_Num = new Uint32(0); 
      var Multiplier = 1; 
      for (let i = 0; i < 4; i++) 
      { 
       Uint32_Num.Set = Uint32_Num.Get + Source_Byte_Array[Start_Position + i] * Multiplier; 
       Multiplier = Multiplier * 256; 
      } 
      return (Uint32_Num.Get); 
     } 
    }; 
    function Load_Page() 
    { 
     var Numbers = [0,1,257,4294967295]; 
     Numbers.forEach(Convert); 
     function Convert(Item, Index) 
     { 
      var Uint32_Number = Item; 
      var Byte_Array = Conversion.Uint32_To_Byte_Array(Uint32_Number); 
      var Uint32_Number_Restored = Conversion.Byte_Array_To_Uint32(Byte_Array, 0); 
      body_Add("Conversion: Source number: " + Uint32_Number.toString() + ", Byte array: " + Byte_Array.toString() + ", Restored number: " + Uint32_Number_Restored.toString() + "<br>"); 
     }; 
    }; 
    </script> 
</head> 
<body onload="Load_Page()"> 
</body> 

+0

結果:轉換:源數字:0,字節數組:0,0,0,0,恢復的數字:0; 轉換:源數量:1,字節數組:1,0,0,0,恢復數量:1; 轉換:源數量:257,字節數組:1,1,0,0,恢復數量:257; 轉換:源數量:4294967295,字節數組:255,255,255,255,恢復數量:4294967295 –

相關問題