【问题标题】:C long double in golanggolang中的C long double
【发布时间】:2017-12-22 19:21:49
【问题描述】:

我正在将一个算法从 C 移植到 Go。我有点困惑。这是 C 函数:

void gauss_gen_cdf(uint64_t cdf[], long double sigma, int n)
{
    int i;
    long double s, d, e;

    //Calculations ...

    for (i = 1; i < n - 1; i++) {
       cdf[i] = s;
    }   
}

在 for 循环中,值“s”被分配给元素“x”数组 cdf。这怎么可能?据我所知,long double 是 float64(在 Go 上下文中)。所以我不应该编译 C 代码,因为我将一个 long double 分配给一个只包含 uint64 元素的数组。但是 C 代码运行良好。

那么有人可以解释一下为什么会这样吗?

非常感谢。

更新:

函数的原始C代码可以在这里找到:https://github.com/mjosaarinen/hilabliss/blob/master/distribution.c#L22

【问题讨论】:

  • 即使在 C 中,您的代码也没有意义,并且可能有一些 undefined behavior。因此,请改进 C 代码以使其符合标准。
  • 为什么不直接使用 Go 中现有的高斯分布实现(例如 go-gaussian),而不是再次移植 C 代码(并引入您自己的错误)?

标签: c go long-double


【解决方案1】:

赋值cdf[i] = s 执行到uint64_t 的隐式转换。如果没有您省略的计算,很难判断这是否是有意的。

在实践中,long double 作为一种类型在不同架构之间存在相当大的差异。 Go 的 float64 是否是合适的替代品取决于您要移植的架构。例如,在 x86 上,long double 是 80 字节的扩展精度类型,但 Windows systems are usually configured in such a way to compute results only with the 53-bit mantissa,这意味着对于您的目的,float64 仍然是等效的。

EDIT 在这种特殊情况下,由源计算的值似乎是静态的并且独立于输入。我只会在 Go 端使用 float64 并查看计算值是否与 C 版本的相同,当在真正的 GNU/Linux 下的 x86 机器上运行时(虚拟化应该没问题),以解决 Windows FPU问题。 x86 的选择只是一个猜测,因为它很可能是原作者使用的。我不了解底层密码学,所以我不能说计算值的差异是否会影响安全性。 (另请注意,C 代码似乎没有正确植入其 PRNG。)

【讨论】:

  • 我更新了问题并添加了指向原始源代码的链接。感谢您对不同架构的解释。
  • 谢谢,我简要查看了 C 源代码并更新了我的答案。
【解决方案2】:

golang 中的 C long double

标题表明对 Go 是否具有类似于 C 中的 long doubleextended precision 浮点类型感兴趣。

答案是:


为什么会这样?

long double s = some_calculation();
uint64_t a = s;

它可以编译,因为与 Go 不同,C 允许某些隐式类型转换。 s 的浮点值的整数部分 将被复制。据推测,s 值已被缩放,以便可以将其解释为fixed-point 值,其中基于链接库源,0xFFFFFFFFFFFFFFFF (2^64-1) 表示值 1.0。为了充分利用此类赋值,可能值得使用具有 64 位精度的扩展浮点类型。

如果我不得不猜测,我会说(与加密相关的)库在这里使用定点,因为他们想确保确定性结果,请参阅:How can floating point calculations be made deterministic?。而且由于扩展精度浮点仅用于初始化查找表,因此在这种情况下使用(可能很慢)math/big 库可能会非常好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-30
    • 2013-09-25
    • 1970-01-01
    • 2010-10-03
    相关资源
    最近更新 更多