我正在尝试将一些Java代码转换为我正在处理的应用程序所需的JavaScript。我被困在一个类及其方法,将double类型的变量转换为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中是否存在类似的内容?此外,如何将变量转换为字节?
提前谢谢你。
答案 0 :(得分:1)
基于Brian's answer和desired representation,您可以按如下方式使用类型化数组:
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();
&#13;
<input type="number" id="input" step="0.01" onchange="interactiveExample()" />
<div id="output"></div>
&#13;
答案 1 :(得分:0)
您可以使用类型化数组和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>
答案 2 :(得分:0)
您可以查看JavaScript Exact Arithmetic。该网站实现了IEEE Double到ByteArray和ByteArray到IEEE Double的转换。 IEEE Double是Java使用的表示形式。因此,此站点生成的字节数组将使用Java转换为精确的double。
我已经提取了底层代码并构建了JRS库(对于J R Stockton,原始代码的作者)。 JRS库提供了两种方法:
图书馆如下。请查看Copyright页面以了解合理使用情况。
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);
};
};