[英]Double to Byte array conversion in javascript
我正在嘗試將一些Java代碼轉換為JavaScript,這正是我正在處理的應用程序所需要的。 我受困於一個類及其將double類型的變量轉換為long類型,然后將long轉換為由8個字節組成的字節數組的方法,該字節表示該長數。 Java代碼如下:
public static byte[] doubleToByteArray(double number)
{
// double to long representation
long longNum = Double.doubleToLongBits(number);
// long to 8 bytes
return new byte[] {(byte)((longNum >>> 56) & 0xFF),
(byte)((longNum >>> 48) & 0xFF),
(byte)((longNum >>> 40) & 0xFF),
(byte)((longNum >>> 32) & 0xFF),
(byte)((longNum >>> 24) & 0xFF),
(byte)((longNum >>> 16) & 0xFF),
(byte)((longNum >>> 8) & 0xFF),
(byte)((longNum >>> 0) & 0xFF)};
} // end doubleToByte(.)
我將如何在JavaScript中執行此操作? 我的第一個問題是doubleToLongBits方法。 JavaScript中是否存在類似的內容? 此外,如何將變量轉換為字節?
先感謝您。
根據Brian的答案和所需的表示形式 ,可以按如下方式使用類型化數組:
function doubleToByteArray(number) { var buffer = new ArrayBuffer(8); // JS numbers are 8 bytes long, or 64 bits var longNum = new Float64Array(buffer); // so equivalent to Float64 longNum[0] = number; return Array.from(new Int8Array(buffer)).reverse(); // reverse to get little endian } function interactiveExample() { var input = parseFloat(document.getElementById('input').value); var output = document.getElementById('output'); var result = doubleToByteArray(input); output.innerHTML = '[' + result[0]; for (var i = 1; i < result.length; i++) { output.innerHTML += ', ' + result[i]; } output.innerHTML += ']'; } document.getElementById('input').value = Math.PI; interactiveExample();
<input type="number" id="input" step="0.01" onchange="interactiveExample()" /> <div id="output"></div>
您可以使用類型化數組和ArrayBuffer
來完成此操作。 我不是浮點表示的專家,但這應該可以滿足您的需求:
function doubleToByteArray(number) { var buffer = new ArrayBuffer(4); var intView = new Int32Array(buffer); var floatView = new Float32Array(buffer); floatView[0] = number; // Debug: display binary representation of `number` // console.log(intView[0].toString(2)); return [ (intView[0] >> 24) & 0xFF, (intView[0] >> 16) & 0xFF, (intView[0] >> 8) & 0xFF, (intView[0] >> 0) & 0xFF, (intView[1] >> 24) & 0xFF, (intView[1] >> 16) & 0xFF, (intView[1] >> 8) & 0xFF, (intView[1] >> 0) & 0xFF ]; } function interactiveExample() { var input = parseFloat(document.getElementById('input').value); var output = document.getElementById('output'); var result = doubleToByteArray(input); output.innerHTML = '[' + result[0]; for (var i = 1; i < result.length; i++) { output.innerHTML += ', ' + result[i]; } output.innerHTML += ']'; } document.getElementById('input').value = Math.PI; interactiveExample();
<input type="number" id="input" step="0.01" onchange="interactiveExample()" /> <div id="output"></div>
您可能會看一下JavaScript Exact Arithmetic 。 該站點實現了將IEEE Double轉換為ByteArray以及將ByteArray轉換為IEEE Double的許多功能。 IEEE Double是Java使用的表示形式。 因此,此站點產生的字節數組將使用Java轉換為精確的double。
我已經提取了底層代碼,並建立了JRS庫(對於原始代碼的作者JR Stockton)。 JRS庫提供了兩種方法:
該庫在下面提供。 請查看版權頁面以了解合理使用情況。
JRS庫如下:
/**
* A library that allow conversion of double to byteArray and vis versa.
* Extracted from "JRS - JavaScript Exact Arithmetic - J R Stockton (See
* http://www.merlyn.demon.co.uk/js-exact.htm#DW4 and
* http://www.merlyn.demon.co.uk/contents.htm#Copy).
*/
JRS = function(){
function numberToBinString(number, binStringLength) {
var A = [], T = null; // number>=0
while (binStringLength--) {
T = number % 2;
A[binStringLength] = T;
number -= T;
number /= 2;
}
return A.join("");
}
function HexFn(fourBitsBinString) {
return parseInt(fourBitsBinString, 2).toString(16);
}
function binStringToHexString(binString) {
return binString.replace(/(\d{4})/g, HexFn );
}
function hexStringToBinString(hexString) {
var binString = "";
for(var i=0; i< hexString.length-1; i+=2) {
binString += numberToBinString(parseInt(hexString.substr(i, 2), 16), 8);
}
return binString;
}
function SngFwd(Sg, Ex, Mt) {
var B = {};
Mt = Math.pow(2, 23) * Mt + 0.5; // round
B.a = 0xFF & Mt;
B.b = 0xFF & (Mt >> 8);
B.c = 0x7F & (Mt >> 16) | (Ex & 1) << 7;
B.d = Sg << 7 | (Ex >> 1);
return B;
}
function DblFwd(Sg, Ex, Mt) {
var B = {};
Mt = Math.pow(2, 52) * Mt;
B.a = 0xFFFF & Mt;
B.b = 0xFFFF & (Mt >> 16);
Mt /= Math.pow(2, 32); // Integers are only 32-bit
B.c = 0xFFFF & Mt;
B.d = Sg << 15 | Ex << 4 | 0x000F & (Mt >> 16);
return B;
}
function CVTFWD(NumW, Qty) { // Function now without side-effects
var Sign = null, Expo = null, Mant = null, Bin = null, nb01 = ""; // , OutW = NumW/4
var Inf = {
32 : {d: 0x7F, c: 0x80, b: 0, a : 0},
64 : {d: 0x7FF0, c: 0, b: 0, a : 0}
};
var ExW = {32: 8, 64: 11}[NumW], MtW = NumW - ExW - 1;
if (isNaN(Qty)) {
Bin = Inf[NumW];
Bin.a = 1;
Sign = false;
Expo = Math.pow(2, ExW) - 1;
Mant = Math.pow(2, -MtW);
}
if (!Bin) {
Sign = Qty < 0 || 1 / Qty < 0; // OK for +-0
if (!isFinite(Qty)) {
Bin = Inf[NumW];
if (Sign)
Bin.d += 1 << (NumW / 4 - 1);
Expo = Math.pow(2, ExW) - 1;
Mant = 0;
}
}
if (!Bin) {
Expo = {32: 127, 64: 1023}[NumW];
Mant = Math.abs(Qty);
while (Mant >= 2) {
Expo++;
Mant /= 2;
}
while (Mant < 1 && Expo > 0) {
Expo--;
Mant *= 2;
}
if (Expo <= 0) {
Mant /= 2;
nb01 = "Zero or Denormal";
}
if (NumW == 32 && Expo > 254) {
nb01 = "Too big for Single";
Bin = {
d : Sign ? 0xFF : 0x7F,
c : 0x80,
b : 0,
a : 0
};
Expo = Math.pow(2, ExW) - 1;
Mant = 0;
}
}
if (!Bin)
Bin = {32: SngFwd, 64: DblFwd}[NumW](Sign, Expo, Mant);
Bin.sgn = +Sign;
Bin.exp = numberToBinString(Expo, ExW);
Mant = (Mant % 1) * Math.pow(2, MtW);
if (NumW == 32)
Mant = Math.floor(Mant + 0.5);
Bin.mnt = numberToBinString(Mant, MtW);
Bin.nb01 = nb01;
return Bin;
}
function CVTREV(BinStr) {
var ExW = {32: 8,64: 11}[BinStr.length];
var M = BinStr.match(new RegExp("^(.)(.{" + ExW + "})(.*)$"));
// M1 sign, M2 exponent, M3 mantissa
var Sign = M[1] == "1" ? -1 : +1;
if (!/0/.test(M[2])) { // NaN or Inf
var X = /1/.test(M[3]) ? NaN : Sign / 0;
throw new Error("Max Coded " + M[3] + " " + X.toString());
}
var Denorm = +M[2] == 0;
if (Denorm) {
console.log("Zero or Denormal");
}
var Expo = parseInt(M[2], 2) - Math.pow(2, ExW - 1) + 1;
var Mant = parseInt(M[3], 2) / Math.pow(2, M[3].length) + !Denorm;
return Sign * Mant * Math.pow(2, Expo + Denorm);
}
this.doubleToHexString = function( /* double */d, /* int */size) {
var NumW = size;
var Qty = d;
with (CVTFWD(NumW, Qty)) {
return binStringToHexString(sgn + exp + mnt);
}
};
this.hexStringToDouble = function (/*String*/hexString, /*int*/size) {
var NumW = size ;
var binString = hexStringToBinString(hexString) ;
var X = new RegExp("^[01]{" + NumW + "}$");
if (!X.test(binString)) {
alert(NumW + " bits 0/1 needed");
return;
}
return CVTREV(binString);
};
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.