Javascript 将javascript整数转换为字节数组并返回
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8482309/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Converting javascript Integer to byte array and back
提问by Ben Reeves
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;
}
I am trying to convert a javascript number to a byte array and then back to a number. However the above functions produce incorrect output with a very large number.
我正在尝试将一个 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
It is my understanding that javascript floats are 53
bits so it shouldn't be overflowing? alert(Math.pow(2,53))
works fine.
我的理解是 javascript 浮点数是53
位,所以它不应该溢出?alert(Math.pow(2,53))
工作正常。
采纳答案by Crozin
In JavaScript bit shifts (>>
, <<
) are always performed on signed, 32-bits integers. This leads to range overflow for large numbers.
在 JavaScript 中,位移 ( >>
, <<
) 总是在有符号的 32 位整数上执行。这会导致大量数字的范围溢出。
回答by Younes
Using the hint provided by Susanoh13, here are the two functions that allow conversion of number from/to ByteArray:
使用 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;
};
回答by Kamil Kie?czewski
try (**
is power operator, <<
and >>>
are bit-shift operators) - intFromBytes
works only for arrays generated from positive integers
try(**
是幂运算符,<<
并且>>>
是位移运算符) -intFromBytes
仅适用于从正整数生成的数组
function getInt64Bytes(x) {
let y= Math.floor(x/2**32);
return [y,(y<<8),(y<<16),(y<<24), x,(x<<8),(x<<16),(x<<24)].map(z=> z>>>24)
}
function intFromBytes(byteArr) {
return byteArr.reduce((a,c,i)=> a+c*2**(56-i*8),0)
}
function getInt64Bytes(x) {
let y= Math.floor(x/2**32);
return [y,(y<<8),(y<<16),(y<<24), x,(x<<8),(x<<16),(x<<24)].map(z=> z>>>24)
}
function intFromBytes(byteArr) {
return byteArr.reduce((a,c,i)=> a+c*2**(56-i*8),0)
}
// TEST
let n = 40*2**40 + 245*2**32 + 194*2**24 + 143*2**16 + 92*2**8 + 40;
let b = getInt64Bytes(n);
let i = intFromBytes(b);
console.log(`number : ${n}`);
console.log(`int to bytes: [${b}]`);
console.log(`bytes to int: ${i}`);
回答by StoicJester
Doing a bit shift is the same as multiplying by 2^(# of bits+1), so instead of shifting the bits val = val<<8
, you can just do val = val*256
. See if that works.
进行位移位与乘以 2^(# of bits+1) 相同,因此val = val<<8
您只需执行val = val*256
. 看看这是否有效。
回答by SET
Brainfwor-style Lodash version. Just 4 lulz! don't use it!
Brainfwor 风格的 Lodash 版本。只需 4 个 lulz!不要使用它!
const uintToArray = (uint, size) => _.chunk(_.padStart(uint, size*2, 0).split(''), 2).map((a)=>parseInt(a[0]+a[1]))
回答by Valery Rode
<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>
回答by Chris Moschini
If you happen to be on Node.js, Buffer
is the correct way to handle any byte array/stream in Javascript/Typescript:
如果您碰巧使用 Node.js,Buffer
那么在 Javascript/Typescript 中处理任何字节数组/流的正确方法是:
https://nodejs.org/api/buffer.html
https://nodejs.org/api/buffer.html
Although the docs are more comprehensive, Stack Overflow recommends code snippets here in case that link 404s, so here are a couple of the most important code examples in that doc:
尽管文档更全面,但 Stack Overflow 建议在此处使用代码片段以防链接 404,因此这里是该文档中最重要的几个代码示例:
// Creates a Buffer containing the UTF-8-encoded bytes for the string 'tést':
// [0x74, 0xc3, 0xa9, 0x73, 0x74] (in hexadecimal notation)
// [116, 195, 169, 115, 116] (in decimal notation)
const buf6 = Buffer.from('tést');
// Creates a Buffer containing the bytes [1, 2, 3].
const buf4 = Buffer.from([1, 2, 3]);