在朗朗的C长双

时间:2017-07-18 05:15:33

标签: c go long-double

我正在将算法从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代码,因为我正在为一个只包含uint64元素的数组赋一个long double。但C代码工作正常。

有人可以解释为什么这有效吗?

非常感谢。

更新:

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

2 个答案:

答案 0 :(得分:0)

作业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仍然可以用于您的目的。

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

答案 1 :(得分:0)

  

golang中的C long double

标题暗示了对Go语言是否具有类似于C语言中的extended precisionlong double浮点类型的兴趣。

答案是:


  

这为什么起作用?

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?。而且由于扩展精度浮点仅用于初始化查找表,因此在这种情况下使用(可能很慢)数学/大库可能会表现得很好。