在 sprintf 中,Windows 和 Unix 系统的四舍五入差异问题

11

我在基于UNIX系统上使用sprintf时遇到问题,它无法正确地四舍五入值。

例如

double tmp = 88888888888885.875
char out[512];

这是88,888,888,888,885.875,只是为了更方便查看。

我正在尝试以以下方式使用它:

sprintf(out, "%021.2f", tmp);
printf("out = %s\n", tmp);

在Windows上,这会导致:

out = 000088888888888885.88

例如在AIX上,但在Linux上也会显示:

out = 000088888888888885.87

为什么会发生这种情况?有任何想法,如何使它在Windows / Unix上的行为相同

谢谢


2
嗯,http://www.ideone.com/UVtft 报告为.88,我的本地SuseLinux也报告相同的结果... - Nim
3
您使用哪些CPU来运行每个操作系统? - chrisaycock
在Linux(Debian 5)AMD64上,我得到了000088888888888885.88 - Charles Salvia
请查看https://dev59.com/pHNA5IYBdhLWcg3wWseK。你的小数(.875)和他的小数(.555)之间的区别在于,你的小数可以在二进制中精确表示;它是7/8。 - rajah9
1
在大多数使用64位IEEE“double”的计算机上,您的两个“out”字符串都等于“tmp”的原始(精确)值。 - aschepler
这是32位的计算机。Win计算机上的CPU是英特尔Xeon(R) x5550 2.6GHz,运行windows vista和VS2010...在Aix上使用XLC编译器。 - grobartn
4个回答

1
你的处理器和编译器使用哪种浮点数表示法?
并不是所有的处理器都使用相同的方式来表示浮点值,甚至编译器也可能选择不同的浮点数表示方法(我认为 Microsoft C++ 编译器甚至有选项可以选择表示法)。
该页面http://www.quadibloc.com/comp/cp0201.htm概述了一些浮点数表示法(尽管那里展示的似乎是相当古老的架构)。 http://msdn.microsoft.com/en-us/library/0b34tf65.aspx描述了 Microsoft Visual C++ 如何存储浮点值。 我无法立即找到 AIX 或 Linux 使用的表示法。
此外,每个编译器都有选项,让您指示您想要如何处理浮点运算。 您希望它们尽可能正确(但可能稍微慢一些)吗? 还是您希望浮点运算尽可能快(但可能不太准确)?

MSVC 无法选择表示方式,它的选项是关于对浮点算术和方法执行优化的。 - Puppy
这里有一个有趣的相关问题:https://dev59.com/X0rSa4cB1Zd3GeqPa_9X - makes

1

对于glibc存在一个错误报告,与您的问题非常相似。这里的主要结论(在评论46中)是double不是一个15位小数的数字,您不应该期望它像那样工作。

作为解决方法,您可以添加一些小数来使它们更好地四舍五入。但是,这个解决方案并不通用,因为它取决于您处理的数字范围。

另一个解决方法可以是乘以一个数以准备进行四舍五入,然后进行四舍五入(例如:2597.625*100 = 259762.5 -> 259763 = 2597.63*100

然而,我认为必须有更聪明的解决方法。


我没有使用你的解决方法,但顶部部分是我需要的,谢谢。 - grobartn

0

这是因为您正在使用具有精度限制的double,这意味着您的88888888888885.875可能在内部被舍入为其他值。

请参阅更多信息类似问题中, 博客维基百科


3
为什么在不同的操作系统上,这个数值被舍入的方式不同?当然,它有精度限制,这就是为什么会得到不同的答案。 - Grammin
2
它可以有所不同,从框架结构到libc的printf做一些打磨。正如您从评论中看到的问题,即使在相同的操作系统(Linux)中,它的行为也会有所不同,因为本质上没有保证它应该表现相同。 - Miguel Ventura

0
在符合IEEE 754标准的实现中,它应该以默认舍入模式打印88888888888885.88。这与浮点精度无关,因为该值可以完全表示;这只是printf在小数点后舍入2位的问题。不知道为什么在某些系统上会看到88888888888885.87

1
OP 可以尝试省略 sprintf(直接将值分配给 double 类型变量),以验证问题是否出现在 printf 中。 - Cascabel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接