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

为什么会这样?任何想法以及如何使其在 Win/Unix 上的行为方式相同

谢谢

4

4 回答 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 使用的表示形式。

此外,每个编译器都有选项,可让您指示您希望如何使用浮点运算。您是否希望它们尽可能正确(但可能会慢一些)?或者您是否希望浮点运算尽可能快(但可能不太正确)?

于 2011-01-10T17:52:15.893 回答
1

有一个glibc 的错误报告与您的问题非常相似。这里的主要结论(在评论 46 中)是 double 不是 15 位十进制数字,你不应该期望它会这样工作。

作为一种解决方法,您可以在数字中添加一些小的内容,以使它们变得更好。但是这个解决方案并不通用,因为它取决于您处理的数字范围。

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

但是我认为必须有更聪明的解决方法。

于 2011-01-11T00:55:30.667 回答
0

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

于 2011-01-10T17:51:35.337 回答
0

那是因为您使用的double是具有准确性限制的,这意味着您88888888888885.875可能在内部被四舍五入。

在类似问题博客维基百科中查看更多信息。

于 2011-01-10T17:34:29.853 回答