sprintf 中 Windows 与基于 Unix 的系统的舍入差异

发布于 2024-10-11 06:32:06 字数 529 浏览 9 评论 0原文

我在基于 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 上表现相同

谢谢

I have problem on UNIX based systems sprintf does not round up properly value.

For example

double tmp = 88888888888885.875
char out[512];

Thats 88,888,888,888,885.875 just to be easier on eyes.
I am giving such specific and big example because it seems it works fine on smaller numbers.

I am trying to use it in following way

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

On windows this results in:

out = 000088888888888885.88

On for example AIX, but shows in Linux as well:

out = 000088888888888885.87

Why is this happening?
Any ideas and how to make it behave same way on Win/Unix

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

最偏执的依靠 2024-10-18 06:32:07

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

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

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

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

There is a bug report for glibc with a problem very similar to yours. The main conclusion (in comment 46) here is that double is not a 15-decimal-digit number and you should not expect it to work like that.

As a workaround you can add something small to your numbers to make them round better. But this solution is not general because it depends on number ranges you deal with.

Another workaround can be multiplying to prepare them for rounding, then rounding (e.g. 2597.625*100 = 259762.5 -> 259763 = 2597.63*100)

However I think there must be smarter workarounds.

我做我的改变 2024-10-18 06:32:07

您的处理器和编译器使用什么浮点表示形式?

并非所有处理器都使用相同的方式来表示浮点值,甚至编译器也可能选择不同的浮点表示方法(我认为 Microsoft C++ 编译器甚至可以选择表示方式)。

页面 http://www.quadibloc.com/comp/cp0201.htm 给出了一些浮点表示的概述(尽管它们似乎是那里显示的相当旧的体系结构)。

http://msdn.microsoft.com/en-us/library/0b34tf65.aspx 描述 Microsoft Visual C++ 如何存储浮点值。我无法立即找到 AIX 或 Linux 使用的表示形式。

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

What floating point representations are used by your processor and your compiler?

Not all processors use the same way to represent floating-point values and even compilers may choose different floating-point representation methods (I think the Microsoft C++ compiler even has options to choose the representation).

The page http://www.quadibloc.com/comp/cp0201.htm gives an overview of some of the floating-point representations (although they seem to be rather old architectures shown there).

http://msdn.microsoft.com/en-us/library/0b34tf65.aspx describes how Microsoft Visual C++ stores floating-point values. I couldn't find immediately what representation is used by AIX or Linux.

Additinally, every compiler has options that let you indicate how you want to work with floating-point operations. Do you want them to be correct as possible (but possibly somewhat slower)? Or do you want floating-point operations to be fast as possible (but possibly less correct)?

似最初 2024-10-18 06:32:07

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

请参阅类似问题中的博客维基百科

That's because you're using double which has accuracy limitations, meaning, your 88888888888885.875 is probably being rounded to something else internally.

See more info in a similar question, in blogs or in wikipedia.

两人的回忆 2024-10-18 06:32:07

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

On an IEEE 754 conformant implementation, it should print 88888888888885.88 in the default rounding mode. This has nothing to do with floating point precision since the value is exactly representable; it's simply a matter of printf's rounding to 2 places after the decimal point. No idea why you're seeing 88888888888885.87 on some systems.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文