JS で float 値のバイトを読み取る方法はありますか? 私が必要としているのは、生の FLOAT または DOUBLE 値を作成する必要のあるバイナリ形式に書き込むことです。そのため、バイトごとの IEEE 754 表現を取得する方法はありますか? もちろん、ライティングについても同じ質問です。
6 に答える
型付き配列でそれを行うことができます:
var buffer = new ArrayBuffer(4);
var intView = new Int32Array(buffer);
var floatView = new Float32Array(buffer);
floatView[0] = Math.PI
console.log(intView[0].toString(2)); //bits of the 32 bit float
または別の方法:
var view = new DataView(new ArrayBuffer(4));
view.setFloat32(0, Math.PI);
console.log(view.getInt32(0).toString(2)); //bits of the 32 bit float
ただし、ブラウザのサポートがどのようなものかはわかりません
TypedArrays がもちろんオプションではないと仮定して、少し高速になるはずの Milos のソリューションの拡張を作成しました (私の場合、それらが利用できない環境で作業しています)。
function Bytes2Float32(bytes) {
var sign = (bytes & 0x80000000) ? -1 : 1;
var exponent = ((bytes >> 23) & 0xFF) - 127;
var significand = (bytes & ~(-1 << 23));
if (exponent == 128)
return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY);
if (exponent == -127) {
if (significand == 0) return sign * 0.0;
exponent = -126;
significand /= (1 << 22);
} else significand = (significand | (1 << 23)) / (1 << 23);
return sign * significand * Math.pow(2, exponent);
}
IEEE-754 32 ビット単精度浮動小数点数を保持する 4 バイトを含む整数を指定すると、ループを使用せずに (ほぼ) 正しい Javascript 数値が生成されます。
同様の問題がありました.javascript番号をバッファに変換し、文字列化せずに解析したかったのです。
function numberToBuffer(num) {
const buf = new Buffer(8)
buf.writeDoubleLE(num, 0)
return buf
}
使用例:
// convert a number to buffer
const buf = numberToBuffer(3.14)
// and then from a Buffer
buf.readDoubleLE(0) === 3.14
これは、現在の Node LTS (4.3.1) 以降で機能します。下位バージョンではテストしていません。
強力なソリューションが必要な場合は Koolinc のスニペットが適していますが、用途が限られている場合は、独自のコードを記述したほうがよいでしょう。バイトの文字列 16 進数表現を浮動小数点数に変換する次の関数を作成しました。
function decodeFloat(data) {
var binary = parseInt(data, 16).toString(2);
if (binary.length < 32)
binary = ('00000000000000000000000000000000'+binary).substr(binary.length);
var sign = (binary.charAt(0) == '1')?-1:1;
var exponent = parseInt(binary.substr(1, 8), 2) - 127;
var significandBase = binary.substr(9);
var significandBin = '1'+significandBase;
var i = 0;
var val = 1;
var significand = 0;
if (exponent == -127) {
if (significandBase.indexOf('1') == -1)
return 0;
else {
exponent = -126;
significandBin = '0'+significandBase;
}
}
while (i < significandBin.length) {
significand += val * parseInt(significandBin.charAt(i));
val = val / 2;
i++;
}
return sign * significand * Math.pow(2, exponent);
}
ウィキペディアには、すべての形式の浮動小数点を双方向に変換するために使用されるアルゴリズムの詳細な説明があり、それらを使用して独自のコードを簡単に記述できます。最初に数値を正規化する必要があるため、数値からバイトへの変換はより困難になるはずです。
このスニペットは役に立ちますか?
var parser = new BinaryParser
,forty = parser.encodeFloat(40.0,2,8)
,twenty = parser.encodeFloat(20.0,2,8);
console.log(parser.decodeFloat(forty,2,8).toFixed(1)); //=> 40.0
console.log(parser.decodeFloat(twenty,2,8).toFixed(1)); //=> 20.0
私はあなたがそれを理解できると思います(blech)が、組み込みの何かがあるかどうかを尋ねていると思います. 私が今まで聞いた限りではありません。仕様のセクション 8.5 および 15.7 を参照してください。