我正在研究一种依赖于所谓的“浮点确定性”的多人游戏,换句话说,所有计算的结果必须与运行游戏的每个人完全相同。这实质上意味着不使用IEEE 754浮点,因为操作可能会导致不同的值,具体取决于舍入模式,使用的融合乘法加法或反平方根指令,不同的libc实现等等。
所以我已经去了所有基本算术运算甚至一些超越函数的定点版本。但是我还是想使用浮点文字来配置游戏变量。在这样做的过程中,我最终得到了一些看起来像是从浮点转换为固定点的代码:
explicit NetFixedPoint(float val)
{
static const StorageType kOne = StorageType(1) << FractionalBits;
m_Value = ((StorageType)(val * kOne));
}
这会在所有平台和处理器架构中给出相同的结果吗?
答案 0 :(得分:5)
简短的回答是“不”。
浮点表示是实现定义的,在将浮点值转换为其他类型时,也会出现浮点类型之间提到的问题类型。
此外,int
的许多属性 - 包括大小,它可以表示的值范围以及表示(例如位组织)也是实现定义的。
净效果是从float
到int
的某些转换在实现之间可靠地工作,而有些则不会。将float
转换为int
时,有些值会向下舍入。 float
也可以表示比int
更大的值范围,并且转换“超出范围”值可能会产生未定义的行为。
不要尝试使用浮点文字初始化变量,而应考虑使用字符串文字(并将值包装在双引号中)。权衡是解析字符串以初始化变量的开销。
答案 1 :(得分:4)
如果浮点值(截断为零)在整数类型中可表示,则严格定义从浮点到整数的转换。如果没有,那么它是未定义的。
其他答案似乎是故意钝的;如果您完全依赖于任何类型的浮点确定性,您需要假设一个符合IEEE-754的实现,而不是C ++标准允许不符合的实现的虚假无理通用性。 IEEE-754。在这种情况下,假设你的编译器没有错误,那么你就有一定程度的确定性,而你的关注点将放在浮点转换为int之外的区域。
答案 2 :(得分:1)
C ++实现从浮点值到整数值的转换的细节大多是一个没有实际意义的点,当C ++标准没有给出关于什么是浮点值的保证。
C ++标准仅保证:
[basic.fundamental]
有三种浮点类型:float,double和long double。 double类型提供至少与float一样多的精度 类型long double提供至少与double一样多的精度。该 float类型的值集是该组值的子集 双重类型; double类型的值集是。的子集 long double类型的值集。 的值表示 浮点类型是实现定义的。
(强调我的)
当&#34;浮点类型的表示的值是实现定义的&#34;时,它几乎排除了一切。对于不同C ++实现之间的浮点到整数值转换一致性,您没有任何保证,因为该标准不保证您可以保证不同的C ++实现&#39;浮点值首先会有一致的值表示!
如果你需要明确定义的浮点语义,你唯一可行的选择是使用专用的,任意精度的数学库,比如Gnu MP,你可以完全控制浮点精度和值转换。