12

64 ビット (8 バイト) の大きな整数を nodejs バッファー オブジェクトにビッグ エンディアン形式で格納したいと考えています。

このタスクに関する問題は、nodejs バッファーが最大 32 ビット整数の書き込みのみをサポートすることです (buf.write32UInt32BE(value, offset) を使用)。だから私は、64ビット整数を分割できないのはなぜだと思いましたか?

var buf = new Buffer(8);

buf.fill(0) // clear all bytes of the buffer
console.log(buf); // outputs <Buffer 00 00 00 00 00 00 00 00>

var int = 0xffff; // as dezimal: 65535

buf.write32UInt32BE(0xff, 4); // right the first part of the int
console.log(buf); // outputs <Buffer 00 00 00 00 00 00 00 ff>

buf.write32UInt32BE(0xff, 0); // right the second part of the int
console.log(buf); // outputs <Buffer 00 00 00 ff 00 00 00 ff>

var bufInt = buf.read32UInt32BE(0) * buf.read32UInt32BE(4);
console.log(bufInt); // outputs 65025

ご覧のとおり、これはほぼ機能します。問題は、64 ビット整数を分割し、それを読み取るときに欠落している 510 を見つけることです。誰かがこれら2つの問題の解決策を示してくれませんか?

4

6 に答える 6

11

あなたが探しているのは次のとおりだと思います:

var bufInt = (buf.readUInt32BE(0) << 8) + buf.readUInt32BE(4);

最初の数値を 8 ビットシフトして (乗算ではなく) 加算すると、次の値が返されます。65535


編集

別の書き方は次のようになります。

var buf = new Buffer(8);
buf.fill(0);

var i = 0xCDEF; // 52719 in decimal

buf.writeUInt32BE(i >> 8, 0); //write the high order bits (shifted over)
buf.writeUInt32BE(i & 0x00ff, 4); //write the low order bits

console.log(buf); //displays: <Buffer 00 00 00 cd 00 00 00 ef>

var bufInt = (buf.readUInt32BE(0) << 8) + buf.readUInt32BE(4);
console.log(bufInt); //displays: 52719
于 2013-02-06T14:12:35.073 に答える
2

0xFFFFの例の値は64ビットではなく16ビットしかないため、混乱しています。

JSnumberタイプはIEEE754浮動小数点値として指定されているため、64ビットの符号なし値を保持できるとは限らないことに注意してください。実際の64ビット整数のサポートが必要な場合は、bignumなどのモジュールを使用して提供する必要があります。そのためのreadmeには、バッファへの値の読み取りと書き込みの例があります。

2^53 - 1浮動小数点値は、精度を失うことなく、までの値のみを表すことができます。この例では、標準のJS番号を使用して次のことを確認できます。

var b = new Buffer([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
var firstHalf = b.readUInt32BE(0); // 4294967295
var secondHalf = b.readUInt32BE(4); // 4294967295

var val = firstHalf * 0x100000000 + secondHalf; // 18446744073709552000

この結果は18446744073709552000、適切な値がである場合です18446744073709551615

var bignum = require('bignum');

var b = new Buffer([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
var val = bignum.fromBuffer(b);

これによりBigNum、値が。のオブジェクトが作成されます18446744073709551615

また、サンプルコードを詳しく説明するために、使用している値は16ビットのみであり、32ビット関数を使用して操作しようとしています。あなたはこれを行うことができます:

var buf = new Buffer(2);

buf.fill(0) // clear all bytes of the buffer
console.log(buf); // outputs <Buffer 00 00>

var int = 0xffff; // as decimal: 65535

// Write it with a standard 16-bit function calls.
buf.writeUInt16BE(int);

// OR write it with 2 8-bit function calls.
buf.writeUInt8(int & 0xff, 0); // right the first part of the int
buf.writeUInt8((int >> 8) & 0xFF, 1); // right the second part of the int
console.log(buf); // outputs <Buffer ff ff>

// Read it as a 16-bit value.
var bufInt = buf.readUInt16BE(0);
console.log(bufInt);

// OR read it as two 8-bit values.
var bufInt = (buf.readUInt8(1) << 8) + buf.readUInt8(0);
于 2013-02-06T17:00:23.340 に答える
2

までの UINT 番号の読み取りと書き込みNumber.MAX_SAFE_INTEGER

これは node.js でのみ機能し、ブラウザ側では移植できません。

function uintToBase62(n) {
  if (n < 0) throw 'unsupported negative integer';

  let uintBuffer;
  if (n < 0x7FFFFFFF) {
    uintBuffer = new Buffer(4);
    uintBuffer.writeUInt32BE(n, 0);
  } else {
    // `~~` double bitwise operator
    // The most practical way of utilizing the power of this operator is to use it as a replacement
    // for Math.floor() function as double bitwise NOT performs the same operation a lot quicker.
    // You can use it, to convert any floating point number to a integer without performance overkill
    // that comes with Math.floor(). Additionally, when you care about minification of your code,
    // you end up using 2 characters (2 tildes) instead of 12.
    // http://rocha.la/JavaScript-bitwise-operators-in-practice
    const big = ~~(n / 0x0100000000);
    const low = (n % 0x0100000000);
    uintBuffer = new Buffer(8);
    uintBuffer.writeUInt32BE(big, 0);
    uintBuffer.writeUInt32BE(low, 4);
  }

  return uintBuffer.toString('hex');
}

それを変換する

function uintFromBase62(uintBuffer) {
  const n = parseInt(uintBuffer.toString('hex'), 16);
  return n;
}
于 2018-06-29T09:06:06.687 に答える
0
// sending time
var sending_time = new Date().getTime();
buffer.writeInt32LE(parseInt(sending_time & 0xffffffff, 10), 16);
buffer.writeInt32LE(parseInt(sending_time / 0xffffffff, 10), 20);
于 2014-02-23T06:21:07.130 に答える
0

64 ビット値の読み取り/書き込み:

const int64 = Date.now()   // 1456909977176 (00 00 01 53 36 9a 06 58)
const b = new Buffer(8)
const MAX_UINT32 = 0xFFFFFFFF

// write
const big = ~~(int64 / MAX_UINT32)
const low = (int64 % MAX_UINT32) - big

b.writeUInt32BE(big, 0)  // 00 00 01 53 00 00 00 00
b.writeUInt32BE(low, 4)  // 00 00 01 53 36 9a 06 58

// read
var time = parseInt(b.toString('hex'), 16)
time == int64 // true

特別なモジュールなしでこのコードを使用します。

アップデート

数字に対してのみ機能します<= Number.MAX_SAFE_INTEGER

于 2016-03-02T09:36:48.697 に答える