C long double in golang

huangapple go评论93阅读模式
英文:

C long double in golang

问题

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

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

    //计算过程...

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

在这个for循环中,变量s的值被赋给了数组cdf的元素x。这怎么可能呢?据我所知,long double在Go语言中对应的是float64类型。所以我不应该能够编译这段C代码,因为我将一个long double赋值给了一个只包含uint64元素的数组。但是这段C代码却可以正常工作。

所以,有人可以解释一下为什么这样可以工作吗?

非常感谢。

更新:

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

英文:

I am porting an algorithm from C to Go. And I got a little bit confused. This is the C function:

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

    //Calculations ...

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

And in the for loop value "s" is assigned to element "x" the array cdf. How is this possible? As far as I know, a long double is a float64 (in the Go context). So I shouldn't be able to compile the C code because I am assigning an long double to an array which just contains uint64 elements. But the C code is working fine.

So can someone please explain why this is working?

Thank you very much.

UPDATE:

The original C code of the function can be found here: https://github.com/mjosaarinen/hilabliss/blob/master/distribution.c#L22

答案1

得分: 1

赋值语句cdf[i] = s会隐式地将其转换为uint64_t类型。在没有给出你省略的计算的情况下,很难确定这是否是有意为之。

实际上,long double作为一种类型在不同的架构上具有相当大的差异。是否将Go的float64作为适当的替代取决于你要移植的架构。例如,在x86架构上,long double是一个80字节的扩展精度类型,但是Windows系统通常配置为仅使用53位尾数计算结果,这意味着float64对于你的目的可能仍然是等效的。

编辑 在这种特殊情况下,源代码计算的值似乎是静态的且与输入无关的。我建议在Go代码中使用float64,并在真实的GNU/Linux环境下(虚拟化应该没问题)在x86机器上运行,看看计算出的值是否与C版本相同,以解决Windows FPU问题。选择x86只是一个猜测,因为原始作者很可能使用了这个架构。我不了解底层的密码学,所以无法确定计算值的差异是否会影响安全性。(还要注意,C代码似乎没有正确地初始化其伪随机数生成器。)

英文:

The assignment cdf[i] = s performs an implicit conversion to uint64_t. It's hard to tell if this is intended without the calculations you omitted.

In practice, long double as a type has considerable variance across architectures. Whether Go's float64 is an appropriate replacement depends on the architecture you are porting from. For example, on x86, long double is an 80-byte extended precision type, but Windows systems are usually configured in such a way to compute results only with the 53-bit mantissa, which means that float64 could still be equivalent for your purposes.

EDIT In this particular case, the values computed by the sources appear to be static and independent of the input. I would just use float64 on the Go side and see if the computed values are identical to those of the C version, when run on a x86 machine under real GNU/Linux (virtualization should be okay), to work around the Windows FPU issues. The choice of x86 is just a guess because it is likely what the original author used. I do not understand the underlying cryptography, so I can't say whether a difference in the computed values impact the security. (Also note that the C code does not seem to properly seed its PRNG.)

答案2

得分: 1

标题表明对于Go语言是否有类似于C语言中的long double扩展精度浮点类型感兴趣。

答案是:

  • Go语言没有原生的扩展精度类型,参见基本类型
  • 但是,Go语言通过math/big库支持任意精度计算。

为什么这段代码能够工作?

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

这段代码能够编译通过,是因为与Go语言不同,C语言允许某些隐式类型转换。浮点数s整数部分将被复制。假设s的值已经被缩放,以便可以将其解释为定点数值,在链接的库源代码中,0xFFFFFFFFFFFFFFFF(2^64-1)表示值1.0。为了充分利用这样的赋值,可能值得使用具有64位精度的扩展浮点类型。

如果我猜的话,我会说这个(与加密相关的)库在这里使用定点数,是因为他们希望确保确定性结果,参见:https://stackoverflow.com/q/7365790/86967。由于扩展精度浮点数仅用于初始化查找表,使用(可能较慢的)math/big库在这种情况下可能表现得非常好。

英文:

> C long double in golang

The title suggests an interest in whether of not Go has an extended precision floating-point type similar to long double in C.

The answer is:


> Why this is working?

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

It compiles because, unlike Go, C allows for certain implicit type conversions. The integer portion of the floating-point value of s will be copied. Presumably the s value has been scaled such that it can be interpreted as a fixed-point value where, based on the linked library source, 0xFFFFFFFFFFFFFFFF (2^64-1) represents the value 1.0. In order to make the most of such assignments, it may be worthwhile to have used an extended floating-point type with 64 precision bits.

If I had to guess, I would say that the (crypto-related) library is using fixed-point here because they want to ensure deterministic results, see: https://stackoverflow.com/q/7365790/86967. And since the extended-precision floating point is only being used for initializing a lookup table, using the (presumably slow) math/big library would likely perform perfectly fine in this context.

huangapple
  • 本文由 发表于 2017年7月18日 13:15:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/45158059.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定