【问题标题】:perl 64 bit ints under the hood引擎盖下的 perl 64 位整数
【发布时间】:2023-04-03 13:16:01
【问题描述】:

我对 perl 中 64 位整数的内部表示感到困惑。

Ubuntu 12.04,perl 5.16.0:

print 18440000000000001000 . "\n";
print 18450000000000001000 . "\n";
print -9220000000000001000 . "\n";
print -9230000000000001000 . "\n";

输出:

18440000000000001000
1.845e+19
-9220000000000001000
-9.23e+18

显然正数溢出并被强制为浮点数,相应的精度损失为 2^64。但是 - 没有为符号位留下空间,那么高达 -2^63 的负数如何表示?

【问题讨论】:

    标签: perl integer 64-bit


    【解决方案1】:

    Perl 数字表示为IVUV。这是SV 结构本身的标志。

    我猜当一个数字被签名时,UV 变成了IV,反之亦然。

    具体来说,查看 SV 定义:

    #define _SV_HEAD_UNION \
    union {                             \
        char*   svu_pv;         /* pointer to malloced string */        \
        IV      svu_iv;                 \
        UV      svu_uv;                 \
        SV*     svu_rv;         /* pointer to another SV */             \
        SV**    svu_array;              \
        HE**    svu_hash;               \
        GP*     svu_gp;                 \
        PerlIO *svu_fp;                 \
    }   sv_u
    

    SvIOKSvUOK 标志可用于查看 SV 的实际有效字段是什么。

    【讨论】:

    • 为不熟悉 perl 内部的人稍微翻译一下:64 位 perl 上的数字标量可以是有符号 无符号 64 位 int,而 perl将在它们之间进行转换,几乎总是做出正确的选择。这意味着您可以轻松地使用介于 -2^63 和 +2^64 之间的数字,超出此范围的后果是“仅”会降级为浮点数。
    • "64-bit perl" 包括 64 位系统上的大多数 perl,以及带有 ivsize=8 的 32 位系统上的 perls,但不包括带有 ivsize=4 的 perls。在这些 perls 上,IVs 是有符号的 32 位,UVs 是无符号的 32 位,但双精度浮点为 NVs 提供了 +/- 2^53 的整数精度。
    猜你喜欢
    • 2018-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-01
    相关资源
    最近更新 更多