JavaScript pack integers and calculate arbitrary precision float:

前端 未结 2 1600
一向
一向 2021-01-15 03:11

I need to do the following in JavaScript and so far been unable to find solutions to do it seamlessly:

  • Grab two integers in a specific order and pack them like
相关标签:
2条回答
  • 2021-01-15 03:24

    I think you need a big number library for JavaScript such as http://jsfromhell.com/classes/bignumber.

    0 讨论(0)
  • 2021-01-15 03:27

    1: Khronos has a specification in progress for a DataView interface as part of the WebGL TypedArray requirements, which combined with Int32Array and Float64Array would let you write your two ints into a buffer, and read them back out as a double.

    Unfortunately browser support for this isn't common yet - to test your browser visit http://html5test.com/ and look at the section entitled "Native binary data".

    Without the TypedArray support above I don't think there's any way to do this using bit-twiddling since Javascript's bit operators treat numbers as 32-bit unsigned values, so you'd have no access to the higher-order bits.

    2: double variables don't have any specific form, IEE754 is just an internal representation.

    3: that's the point at which you can attempt to show the actual precision. Unfortunately the built-in method, e.g. Number.toFixed(), doesn't support showinng more than 20 decimal places. You will need to parse the exponential form and manually construct a string with the appropriate number of leading zeros.

    NB - the exponent range of a double is 2^1024, not 10^1024, hence the real limit is actually ~1.0E±308 - your example figure is smaller than that range.

    EDIT actually, there might be a way, but I can't guarantee the precision of this:

    1. take your two integers, call them hi and lo.
    2. extract the exponent - exp = (hi >> 20) & 0x7ff
    3. extract the sign - sign = (hi >> 31)
    4. extract the mantissa - ((hi & 0xfffff) * Math.pow(2, 32) + lo) / Math.pow(2, 52)
    5. result = (1 + m) * (Math.pow(2.0, exp - 1023))
    6. if (sign) result *= -1

    EDIT 2 - it works! See http://jsfiddle.net/alnitak/assXS/

    var hex2double = function(input) {
    
        var hi = parseInt(input.substring(0, 8), 16);
        var lo = parseInt(input.substring(8   ), 16);
    
        var p32 = 0x100000000;
        var p52 = 0x10000000000000;
    
        var exp = (hi >> 20) & 0x7ff;
        var sign = (hi >> 31);
        var m = 1 + ((hi & 0xfffff) * p32 + lo) / p52;
        m = exp ? (m + 1) : (m * 2.0);
    
        return (sign ? -1 : 1) * m * Math.pow(2, exp - 1023);
    };
    

    Enter a floating point number at http://babbage.cs.qc.edu/IEEE-754/Decimal.html, take the resulting hex string from the bottom row of output, and pass it to the function above. You should see an alert containing the original value.

    EDIT 3 code fixed to account for the special case when the exponent bits are all zero.

    0 讨论(0)
提交回复
热议问题