簡體   English   中英

JavaScript中的雙字節數組轉換

[英]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庫提供了兩種方法:

  • doubleToHexString():將IEEE Double轉換為十六進制字符串
  • hexStringToDouble():將十六進制字符串轉換為IEEE Double

該庫在下面提供。 請查看版權頁面以了解合理使用情況。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM