JavaScript 打包整数并计算任意精度浮点数:

发布于 2024-11-24 21:26:29 字数 998 浏览 6 评论 0原文

我需要在 JavaScript 中执行以下操作,但到目前为止还无法找到无缝执行此操作的解决方案:

  • 以特定顺序获取两个整数并像 Python 的 struct 模块一样打包它们。
  • 这个打包值(支持与主机不同的字节序的好处)将被转换为 64 位浮点(双精度)。它们必须是任意的,因此我可能会得到整数的指数表示(例如,它们可能是 0xdeadbeef 和 500):

    以表达式形式: 1.0883076389305e-311 1.0883076389305000 * 10 ^ - 311

  • 我需要将其转换为任意精度、非指数形式,所以:

    0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000001088307638930500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

  • 那个数字转换为字符串:)

我还没有找到在Javascript中执行此操作的方法,我必须输出一些必须支持任意精度的数字,或者至少达到双精度数的 1024 指数(或者说 400)。

谢谢!!

注意:我确实需要“打包/解包”来忠实地表示转换为双精度/64 位浮点数的这两个数字。但我不关心导出到字符串或原始缓冲区。只要我获得双精度的任意精度双精度表示,这一切都很好。

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 Python's struct module.
  • This packed value, (bonus for supporting different endianness than host) will be turned into a 64 bit float (double). They must be arbitrary thus I might get an exponent representation of the integer (say, they could be 0xdeadbeef and 500):

    In exp form:
    1.0883076389305e-311
    1.0883076389305000 * 10 ^ - 311

  • I need to convert it to the arbitrary precision, non-exponent form, so:

    0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000108830763893050000000000000000000000000000000000000000000000000000000000000000000000000000

  • That number converted to a string :)

I haven't found a way to do this in Javascript and I have to output some numbers like that which must support arbitrary precision, or at least, of a scale up to the 1024 exponent (or, say 400) of doubles.

Thanks!!

Note: I do need the "packing/unpacking' to be a faithful representation of those two numbers converted to a double/64bit float. But I don't care about, say, exporting to a string or raw buffer. As long as I get an arbitrary precision double representation for the double it's all fine.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

少年亿悲伤 2024-12-01 21:26:29

1:Khronos 有一个正在制定的规范< code>DataView 接口作为 WebGL TypedArray 要求的一部分,与 Int32Array 相结合em> 和Float64Array 可以让您将两个 int 写入缓冲区,并将它们作为双精度数读回。

不幸的是,浏览器对此的支持还不常见 - 要测试您的浏览器,请访问 http://html5test.com/ 并查看在标题为“本机二进制数据”的部分。

如果没有上面的 TypedArray 支持,我认为没有任何方法可以使用位旋转来做到这一点,因为 Javascript 的位运算符将数字视为 32 位无符号值,所以你' d 无法访问高阶位。

2:double变量没有任何特定的形式,IEE754只是一种内部表示。

3:这是您可以尝试显示实际精度的点。不幸的是,内置方法,例如Number.toFixed(),不支持显示超过20位小数。您将需要解析指数形式并手动构造一个具有适当数量的前导零的字符串。

注意 - 双精度数的指数范围是 2^1024,而不是 10^1024,因此真正的限制实际上是 ~1.0E±308 - 您的示例数字小于该范围。

编辑实际上,可能有一种方法,但我不能保证其精度:

  1. 取两个整数,称它们为 hilo
  2. 提取指数 - exp = (hi >> 20) & 0x7ff
  3. 提取符号 - sign = (hi >> 31)
  4. 提取尾数 - ((hi & 0xfffff) * Math.pow(2, 32) + lo) / Math.pow(2, 52)
  5. 结果 = (1 + m) * (Math.pow(2.0, exp - 1023))
  6. if (sign) result *= -1

编辑 2 - 它有效!请参阅 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);
};

http://babbage.cs.qc.edu/IEEE-754/Decimal.html,从输出的底行获取生成的十六进制字符串,并将其传递给上面的函数。您应该看到包含原始值的警报。

修复了EDIT 3代码,以解决指数位全为零时的特殊情况。

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.

笔落惊风雨 2024-12-01 21:26:29

我认为你需要一个 JavaScript 的大数字库,例如 http://jsfromhell.com/classes/bignumber

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文