在所有平台和处理器架构中,从float到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的实现的伪造的无偿通用性。 在这种情况下,假设您的编译器没有错误,那么您有一定程度的确定性,并且您的关注点将在浮动到整数转换之外的区域。

C ++实现从浮点值到整数值的转换的细节大多是没有实际意义的,当C ++标准首先没有给出浮点值的保证。

C ++标准只保证您:

[basic.fundamental]

有三种浮点类型:float,double和long double。 double类型提供至少与float一样多的精度,long double类型提供至少与double一样多的精度。 float类型的值集是double类型的值集的子集; double类型的值集是long double类型的值集的子集。 浮点类型的值表示是实现定义的。

(强调我的)

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

如果您需要明确定义的浮点语义,那么您唯一可行的选择是使用专用的,任意精度的数学库,如Gnu MP,您可以完全控制浮点精度和值转换。