【问题标题】:Erlang NIF number return typesErlang NIF 数字返回类型
【发布时间】:2016-09-01 18:54:38
【问题描述】:

我正在尝试使用 NIF,但我对 Erlang 使用的数字类型感到困惑,因为我的精度有些奇怪。

这是一个例子:

erlang:band(18446744073709551614, 5) == 4

从一个看起来像这样的 NIF 内部:

long long l, r;

enif_get_long(env, argv[0], &l);
enif_get_long(env, argv[1], &r);

return enif_make_long(env, l & r);

结果我得到了1

这与 C 层没有保持正确的数字“大小”有关吗?还是enif_(get|make)_long 不是处理这种大小的数字的正确方法?或者仅仅是 NIF 无法处理这么大的数字?

【问题讨论】:

    标签: c erlang erlang-nif


    【解决方案1】:

    184467440737095516142^64 - 2,因此不能放入 long long,它很可能是一个 64 位有符号整数,范围为 -(2^63)(2^63)-1。此外,enif_get_long 需要 long int,而不是 long long。您还应该得到从enif_get_long 返回的错误值,因为根据您未检查的docs 溢出。

    要处理直到2^64 - 1 的数字(包括有问题的数字),您可以使用enif_get_uint64

    这段代码应该可以工作(未经测试):

    ErlNifUInt64 l, r;
    enif_get_uint64(env, argv[0], &l);
    enif_get_uint64(env, argv[1], &r);
    return enif_make_uint64(env, l & r);
    

    您还应该检查enif_get_* 的返回值,以确保您没有处理未初始化的数据。

    【讨论】:

    • 该示例确实有效,感谢您的解释和解释。我没有意识到这种情况下存在ErlNifUInt64。我肯定会添加检查,我只是在尝试让它工作:)。 ErlNifUInt64 基本上会覆盖 Erlang 允许的任何数字吗?
    • 不,只有018446744073709551615(无符号64 位整数的范围)。
    • 那么处理负数和正数的适当方法是否只是检查 Erlang 端的符号并分别在 NIF 中实现?
    • 你想支持什么范围的数字?
    • 理想情况下,你可以在 Erlang 中使用任何东西(我正在考虑将一些东西移植到 NIF 以使其更快,但希望保留 Erlang 版本的行为)
    猜你喜欢
    • 2013-01-03
    • 2016-03-30
    • 2016-10-06
    • 2015-01-02
    • 2012-01-07
    • 1970-01-01
    • 2020-05-17
    • 2011-03-25
    • 2013-01-03
    相关资源
    最近更新 更多