双到字节在JavaScript阵列转换(Double to Byte array conversio

2019-10-21 00:54发布

我想一些Java代码转换成这是需要我工作的应用程序的JavaScript。 我停留在一个类及其方法该double类型的变量转换为长,然后长为一个字节数组,包含表示该长数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中? 此外,如何投下变量为一个字节对象?

先感谢您。

Answer 1:

基于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> 



Answer 2:

You might look at JavaScript Exact Arithmetic. This site implements, among many things, conversion of IEEE Double to ByteArray and ByteArray to IEEE Double. IEEE Double is the representation used by Java. So, a byte array produced by this site will convert to the exact double using Java.

I have extracted the underlying code and build up the library JRS (for J R Stockton, the author of the original code). The JRS library offers two methods:

  • doubleToHexString(): converts an IEEE Double to an hexadecimal string
  • hexStringToDouble(): converts an hexadecimal string to an IEEE Double

The library is provided below. Please take a look at the Copyright page for fair usage.

The JRS library is as follows:

/**
 * 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);
    };
};


Answer 3:

您可以使用类型数组和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> 



文章来源: Double to Byte array conversion in javascript