在 C 中将 float64 转换为 uint64 时有精度损失吗?假设只有数据的整数部分是有意义的

Any precision loss when converting float64 to uint64 in C? assuming only the whole number part of the data is meaningful

我有一个 TCP 协议的计数器字段,用于跟踪发送的样本。它被定义为 float64。我需要将此协议转换为另一个协议,其中计数器定义为 uint64。

我能否安全地将 float64 值存储在 uint64 中而不丢失数据整数部分的任何精度?假设小数部分可以忽略。

编辑:对不起,如果我没有描述清楚。没有代码。我只是在查看两个不同的协议文档,看看是否可以将其中一个翻译成另一个。

请将 float64 视为 double,文档写得不好而且很旧。

非常感谢。

我假设您询问的是 64 位浮点值,例如 https://en.wikipedia.org/wiki/Double-precision_floating-point_format 中记录的 IEEE Binary64。

将表示为 64 位 IEEE 浮点值的 double 转换为 uint64_t 不会丢失值整数部分的任何精度,只要该值本身是非负数并且小于 264。但是,如果该值大于 253,则表示为 double 不允许完全精确,因此导致该值的任何计算都可能是不准确的。

请注意,反过来是错误的,IEEE 浮点数的精度低于 64 位 uint64_t,因此接近但不同的大值将转换为相同的 double 值。

请注意,作为 64 位实现的计数器 double 本质上受到浮点类型精度的限制。将大于 253 的值增加 1 可能根本没有效果。使用浮点类型来实现数据包计数器似乎是一个非常糟糕的主意。直接使用 uint64_t 计数器似乎是更安全的选择。你只需要担心在 264 处回绕,你可以在不太可能的情况下检查这个条件,你实际上希望数到那么远。

如果您无法更改格式,请验证浮点值是否在转换范围内,如果不在范围内,则存储一个适当的值:

#include <stdint.h>

...

double v = get_64bit_value();
uint64_t result;

if (v < 0) {
    result = 0;
} else
if (v >= (double)UINT64_MAX) {
    result = UINT64_MAX;
} else {
    result = (uint64_t)v;
}

是的,精度丢失了。负数无法正确转换为 uint64(因为此类型是无符号的),以及大于 2^64-1 的数字。在所有其他情况下,转换都是精确的(前提是您将 float64 值视为精确且舍入正确)。