2011-01-10 40 views
9

我在基於UNIX的系統上遇到問題,sprintf沒有正確收集值。sprintf中Windows與基於Unix的系統的舍入差異

例如

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的

感謝

+2

erm,http://www.ideone.com/UVtft報告`.88`,我本地的SuseLinux報告一樣... – Nim 2011-01-10 17:29:34

+3

你在每個操作系統上使用了哪些CPU? – chrisaycock 2011-01-10 17:33:01

+0

在Linux(Debian 5)AMD64上,我得到`000088888888888885.88` – 2011-01-10 17:41:18

回答

1

對於glibc,有一個bug report,其問題與您的問題非常相似。這裏的主要結論(在評論46中)是double不是15位數字的數字,你不應該指望它像那樣工作。

作爲一種解決方法,您可以在數字中添加一些小數字以使其更好。但是這個解決方案並不普遍,因爲它取決於你處理的數字範圍。

另一個解決方法可以相乘,以用於準備四捨五入它們,然後舍入(例如2597.625*100 = 259762.5 -> 259763 = 2597.63*100

但是我認爲必須有更聰明的變通方法。

0

那是因爲你使用double具有精度限制,這意味着,你的88888888888885.875可能正在四捨五入到別的內部。

查看更多信息in a similar question,在blogswikipedia

0

在符合IEEE 754的實現中,它應該在默認舍入模式下打印88888888888885.88。這與浮點精度無關,因爲該值是完全可表示的;這僅僅是printf在小數點後四捨五入到兩個地方的問題。不知道爲什麼你在某些系統上看到88888888888885.87

1

處理器和編譯器使用哪些浮點表示?

並非所有處理器都使用相同的方式來表示浮點值,甚至編譯器可能會選擇不同的浮點表示方法(我認爲Microsoft C++編譯器甚至可以選擇表示形式)。

頁面http://www.quadibloc.com/comp/cp0201.htm給出了一些浮點表示的概述(儘管它們似乎是那裏顯示的相當古老的體系結構)。

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

另外,每個編譯器都有一些選項可以指示您想如何使用浮點操作。你是否希望它們儘可能正確(但可能有點慢)?或者你想要浮點運算儘可能快(但可能不太正確)?