英文:
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 < 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
的扩展精度浮点类型感兴趣。
答案是:
为什么这段代码能够工作?
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:
- Not as a primitive, see Basic types.
- But arbitrary precision is supported by the math/big library.
> 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论