从浮点型到 int 的转换在所有平台和处理器架构中是否一致?



我正在开发一款多人游戏,它依赖于所谓的"浮点决定论",或者换句话说,所有计算的结果在运行游戏的每个人中都必须完全相同。 这实质上意味着不使用 IEEE 754 浮点数,因为操作可能会产生不同的值,具体取决于舍入模式、使用的融合乘加或平方反比根指令、不同的 libc 实现等。

所以我做了所有基本算术运算的定点版本,甚至一些超越函数。 但是,我仍然想使用浮点文字来配置游戏变量。 在这样做的过程中,我最终得到了一些看起来像这样的代码,从浮点转换为定点:

explicit NetFixedPoint(float val)
{
static const StorageType kOne = StorageType(1) << FractionalBits;
m_Value = ((StorageType)(val * kOne));
}

这会在所有平台和处理器架构上给我带来相同的结果吗?

简短的回答是"否"。

浮点表示形式是实现定义的,在将浮点值转换为其他类型的浮点类型时,也会发生浮点类型之间提到的关注点类型。

此外,还定义了int的许多属性 - 包括大小,它可以表示的值范围和表示(例如位的组织)。

净效果是,从floatint的一些转换将在实现之间可靠地工作,而有些则不会。 将float转换为int时,某些值将向下舍入。float还可以表示比int更大的值范围,并且转换"超出范围"的值可能会产生未定义的行为。

与其尝试使用浮点文本来初始化变量,不如考虑使用字符串文本(并将值括在双引号中)。 权衡是解析字符串以初始化变量的开销。

如果向零截断的浮点值可在整数类型中表示,则严格定义从浮点到整数的转换。如果没有,则未定义。

其他答案似乎是故意迟钝的;如果你依赖于任何类型的浮点决定论,你需要假设一个符合IEEE-754的实现,而不是C++标准允许不符合IEEE-754的实现的虚假的无端通用性。在这种情况下,假设您的编译器没有错误,您具有相当程度的确定性,并且您的关注点将集中在浮点到int转换以外的领域。

C++实现从浮点值到整数值的转换细节大多是一个有争议的问题,因为C++标准首先并没有对浮点值给出太多保证。

C++标准仅向您保证:

[基础.基础]

有三种浮点类型:浮点型、双精度型和长型双精度型。 双精度类型至少提供与浮点数一样多的精度,并且 长双精度型提供至少与双精度一样多的精度。这 浮点类型的值集是 双倍类型;双精度类型的值集是 长双精度类型的值集。的值表示形式 浮点类型是实现定义的。

(强调我的)

当"浮点类型的表示值是实现定义的"时,这几乎排除了一切。您不能保证不同C++实现之间的浮点值到整数值转换的一致性,因为该标准不能保证不同C++实现的浮点值首先具有一致的值表示!

如果您需要定义良好的浮点语义,您唯一现实的选择是使用特殊用途的任意精度数学库,例如 Gnu MP,您可以在其中完全控制浮点精度和值转换。

最新更新