JavaScript pack integers and calculate arbitrary precision float:

三世轮回 提交于 2019-12-01 10:37:02

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.

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!