How to convert a floating point number to its binary representation (IEEE 754) in Javascript?

前端 未结 2 828
说谎
说谎 2021-02-01 18:19

What\'s the easiest way to convert a floating point number to its binary representation in Javascript? (e.g. 1.0 -> 0x3F800000).

I have tried to do it manually, and this

相关标签:
2条回答
  • 2021-02-01 18:30

    new technologies are making this easy and probably also more forward-compatible. I love extending built in prototypes, not everyone does. So feel free to modify following code to classical procedural approach:

    (function() {
        function NumberToArrayBuffer() {
            // Create 1 entry long Float64 array
            return [new Float64Array([this]).buffer];
        }
        function NumberFromArrayBuffer(buffer) {
            // Off course, the buffer must be at least 8 bytes long, otherwise this is a parse error
            return new Float64Array(buffer, 0, 1)[0];
        }
        if(Number.prototype.toArrayBuffer)  {
            console.warn("Overriding existing Number.prototype.toArrayBuffer - this can mean framework conflict, new WEB API conflict or double inclusion.");
        }
        Number.prototype.toArrayBuffer = NumberToArrayBuffer;
        Number.prototype.fromArrayBuffer = NumberFromArrayBuffer;
        // Hide this methods from for-in loops
        Object.defineProperty(Number.prototype, "toArrayBuffer", {enumerable: false});
        Object.defineProperty(Number.prototype, "fromArrayBuffer", {enumerable: false});
    })();
    

    Test:

    (function() {
        function NumberToArrayBuffer() {
            // Create 1 entry long Float64 array
            return new Float64Array([this.valueOf()]).buffer;
        }
        function NumberFromArrayBuffer(buffer) {
            // Off course, the buffer must be ar least 8 bytes long, otherwise this is a parse error
            return new Float64Array(buffer, 0, 1)[0];
        }
        if(Number.prototype.toArrayBuffer)  {
            console.warn("Overriding existing Number.prototype.toArrayBuffer - this can mean framework conflict, new WEB API conflict or double inclusion.");
        }
        Number.prototype.toArrayBuffer = NumberToArrayBuffer;
        Number.fromArrayBuffer = NumberFromArrayBuffer;
        // Hide this methods from for-in loops
        Object.defineProperty(Number.prototype, "toArrayBuffer", {enumerable: false});
        Object.defineProperty(Number, "fromArrayBuffer", {enumerable: false});
    })();
    var test_numbers = [0.00000001, 666666666666, NaN, Infinity, -Infinity,0,-0];
    console.log("Conversion symethry test: ");
    test_numbers.forEach(
          function(num) {
                   console.log("         ", Number.fromArrayBuffer((num).toArrayBuffer()));
          }
    );
    
    console.log("Individual bytes of a Number: ",new Uint8Array((666).toArrayBuffer(),0,8));
    <script src="https://getfirebug.com/firebug-lite-debug.js"></script>

    0 讨论(0)
  • 2021-02-01 18:49

    Here's a function that works on everything I've tested it on, except it doesn't distinguish -0.0 and +0.0.

    It's based on code from http://jsfromhell.com/classes/binary-parser, but it's specialized for 32-bit floats and returns an integer instead of a string. I also modified it to make it faster and (slightly) more readable.

    // Based on code from Jonas Raoni Soares Silva
    // http://jsfromhell.com/classes/binary-parser
    function encodeFloat(number) {
        var n = +number,
            status = (n !== n) || n == -Infinity || n == +Infinity ? n : 0,
            exp = 0,
            len = 281, // 2 * 127 + 1 + 23 + 3,
            bin = new Array(len),
            signal = (n = status !== 0 ? 0 : n) < 0,
            n = Math.abs(n),
            intPart = Math.floor(n),
            floatPart = n - intPart,
            i, lastBit, rounded, j, exponent;
    
        if (status !== 0) {
            if (n !== n) {
                return 0x7fc00000;
            }
            if (n === Infinity) {
                return 0x7f800000;
            }
            if (n === -Infinity) {
                return 0xff800000
            }
        }
    
        i = len;
        while (i) {
            bin[--i] = 0;
        }
    
        i = 129;
        while (intPart && i) {
            bin[--i] = intPart % 2;
            intPart = Math.floor(intPart / 2);
        }
    
        i = 128;
        while (floatPart > 0 && i) {
            (bin[++i] = ((floatPart *= 2) >= 1) - 0) && --floatPart;
        }
    
        i = -1;
        while (++i < len && !bin[i]);
    
        if (bin[(lastBit = 22 + (i = (exp = 128 - i) >= -126 && exp <= 127 ? i + 1 : 128 - (exp = -127))) + 1]) {
            if (!(rounded = bin[lastBit])) {
                j = lastBit + 2;
                while (!rounded && j < len) {
                    rounded = bin[j++];
                }
            }
    
            j = lastBit + 1;
            while (rounded && --j >= 0) {
                (bin[j] = !bin[j] - 0) && (rounded = 0);
            }
        }
        i = i - 2 < 0 ? -1 : i - 3;
        while(++i < len && !bin[i]);
        (exp = 128 - i) >= -126 && exp <= 127 ? ++i : exp < -126 && (i = 255, exp = -127);
        (intPart || status !== 0) && (exp = 128, i = 129, status == -Infinity ? signal = 1 : (status !== status) && (bin[i] = 1));
    
        n = Math.abs(exp + 127);
        exponent = 0;
        j = 0;
        while (j < 8) {
            exponent += (n % 2) << j;
            n >>= 1;
            j++;
        }
    
        var mantissa = 0;
        n = i + 23;
        for (; i < n; i++) {
            mantissa = (mantissa << 1) + bin[i];
        }
        return ((signal ? 0x80000000 : 0) + (exponent << 23) + mantissa) | 0;
    }
    
    0 讨论(0)
提交回复
热议问题