跨平台/编译器一致的浮点数sprintf

kov*_*rex 32 c++ lua printf string-formatting

我们有一个需要确定性的游戏,因为它是多人游戏模型的一部分.我们还使用Lua,它在sprintf内部使用(格式为%.14g).

打印数字如0.00001时会出现问题.在某些情况下,它会打印1e-05,在某些情况下,它会打印1e-005(额外为零).

例如,当使用Visual Studio 2015进行编译时,它会进行打印1e-005,并使用Visual Studio 2013进行打印1e-05.我尝试了不同的区域设置,但似乎没有任何效果.

问题是:实现确定性结果的最佳解决方案什么? 我不关心科学记谱法是否标准化或消除.

我想到的解决方案:

  • 当我使用%f符号时,它不会忽略无关紧要的零,因此%.14f会导致不切实际的长数.
  • 使用自定义sprintf方法(从某些标准库粘贴的副本)
  • 使用一些我没想过的特殊格式(我只使用它作为参考:http://www.cplusplus.com/reference/cstdio/printf/)

Col*_*Two 18

你可以切换到LuaJIT.它在平台之间一致地格式化数字

扩展页面:

tostring()等规范化NaN和±Inf

所有数字到字符串的转换始终将非有限数字转换为所有平台上的相同字符串.NaN导致"nan",正无穷大导致"inf",负无穷大导致"-inf".

tonumber()等使用内置字符串进行数字转换

所有字符串到数字的转换在所有平台上一致地转换十进制和十六进制的整数和浮点输入.strtod()不再使用,这避免了C库实现不良的许多问题.内置转换函数根据IEEE-754标准提供完全精度,它独立于当前语言环境工作,并支持十六进制浮点数(例如0x1.5p-3).


kov*_*rex 4

一年后,我们就是这样解决的。

我们下载了自定义打印实现(三重奏)并强制使用此实现,而不是 lua(以及我们的源代码)中的系统实现。

我们也不得不改变

long double trio_long_double_t;
Run Code Online (Sandbox Code Playgroud)

double trio_long_double_t;
Run Code Online (Sandbox Code Playgroud)

在 triodef.h 中确保 Visual studio 和 linux/mac 给出相同的结果。