golang 中的 C long double
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;
//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
赋值 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 long double in golang
标题表明对 Go 是否在 C 中有 extended precision floating-point type similar to long double
感兴趣。
答案是:
- 不是原始人,参见 Basic types。
- 但是任意精度被math/big library支持。
Why this is working?
long double s = some_calculation();
uint64_t a = s;
它可以编译,因为与 Go 不同,C 允许某些隐式类型转换。 s
的 floating-point 值的 整数部分 将被复制。据推测,s
值已按比例缩放,因此可以将其解释为 fixed-point value where, based on the linked library source, 0xFFFFFFFFFFFFFFFF
(2^64-1) 表示值 1.0。为了充分利用此类分配,使用具有 64 个精度位的扩展 floating-point 类型可能是值得的。
如果非要我猜的话,我会说 (crypto-related) 库在这里使用 fixed-point 因为他们想确保确定性的结果,请参阅:How can floating point calculations be made deterministic?。由于 extended-precision 浮点数仅用于初始化查找 table,因此使用(可能很慢)math/big 库在这种情况下可能会表现得非常好。
我正在将算法从 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
赋值 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 long double in golang
标题表明对 Go 是否在 C 中有 extended precision floating-point type similar to long double
感兴趣。
答案是:
- 不是原始人,参见 Basic types。
- 但是任意精度被math/big library支持。
Why this is working?
long double s = some_calculation();
uint64_t a = s;
它可以编译,因为与 Go 不同,C 允许某些隐式类型转换。 s
的 floating-point 值的 整数部分 将被复制。据推测,s
值已按比例缩放,因此可以将其解释为 fixed-point value where, based on the linked library source, 0xFFFFFFFFFFFFFFFF
(2^64-1) 表示值 1.0。为了充分利用此类分配,使用具有 64 个精度位的扩展 floating-point 类型可能是值得的。
如果非要我猜的话,我会说 (crypto-related) 库在这里使用 fixed-point 因为他们想确保确定性的结果,请参阅:How can floating point calculations be made deterministic?。由于 extended-precision 浮点数仅用于初始化查找 table,因此使用(可能很慢)math/big 库在这种情况下可能会表现得非常好。