2009-02-22 44 views
7

我越來越從round()roundf()功能意想不到的結果在math.h庫。下面是示例代碼:我如何錯誤地使用C中的round()函數?

#include <stdio.h> 
#include <math.h> 

int main(void) 
{ 
    float f; 
    double d; 

    /* Note man page says that roundf() returns a float 
     and round() returns a double */ 
    f = roundf(1.2); 
    d = round(1.2); 

    printf("%f\n", f); 
    printf("%lf\n", d); 

    return 0; 
} 

當我complie並運行該程序,我得到:

gcc -lm round.c 
./a.out 
288.000000 
524288.000000 

奇怪吧?

更新:隨着答案我已經證實,代碼在新的編譯器上正常工作。 (我認爲%lf不是正確的printf說明符,但在這種情況下不會影響最終結果。)我需要弄清楚爲什麼編譯器可能會這樣做,因爲我運行的代碼使用了round()和已經在同一臺機器上編譯。當我弄明白的時候我會更新這篇文章。

gcc -v 
Reading specs from /usr/lib/gcc-lib/i386-slackware-linux/2.95.3/specs 
gcc version 2.95.3 20010315 (release) 
+0

我不明白爲什麼。它在我的情況下輸出1.000000。 – tvanfosson 2009-02-22 22:24:22

+0

Upvoted抵消downvote。這是一個完全有效的問題。如果我有這種行爲,我也會問這個問題。 – 2009-02-22 22:31:48

+0

請更新您的編譯器。 GCC 2.95.3它已經8歲了......這些年來已經修復了數百萬的錯誤。 – 2009-02-22 23:04:13

回答

10

如果編譯代碼而不告訴gcc編譯C99模式(-std=c99)並告訴它不知道「特殊內建」函數(使用​​),則可能會失敗。然後它假定您一輪/ roundf功能是因爲在預C99倍定義爲

int round(); 
int roundf(); 

沒有這樣的功能呢,所以它沒有一個聲明,隱式聲明它們然後。這顯然會失敗,因爲調用方將返回值視爲int,而被調用方(在鏈接庫中這些函數的定義中)返回一個浮點數。我得到這些結果,例如:

[[email protected] cpp]$ ./a.out 
1065353216.000000 
-1048576.000000 
[[email protected] cpp]$ 

不是說你,現在你可以在返回值轉換爲浮動,並確定認爲。呃,情況更糟。返回值甚至不保證與返回的浮點數有關。調用方從它知道返回整數的位置讀取數據。但是你的編譯器可能會在被調用方的另一個地方(比如說,在一個浮點指針寄存器中)返回浮點數。上面實際上可以做任何事情,包括中止程序,因爲它的行爲不明確。

那麼,你能做些什麼來使它工作?通過編譯器std=c99標誌或使用其他方式來圓(地板就是其中之一),它不需要這些功能

gcc -std=c99 test.c -lm 

man 3 round手冊頁。但是,如果你有一個非常古老的GCC - 我不確定它是否支持足夠的C99來進行切換。查看當時的聯機幫助頁中描述的功能測試宏。

3

當我編譯並(在Cygwin的下GCC)運行這個確切的代碼我得到:

$ ./a.exe 
1.000000 
1.000000 

有多新的編譯器?編譯器錯誤是我能想到的,因爲gcc -Wall也不會給出任何警告。

要添加一些進一步的信息this forum thread似乎表明改變編譯器到一個更新的版本修復它。如果這不適合你,你需要提供更多的編譯器和操作系統的細節,但鑑於這似乎適用於三個不同平臺上的其他人,看起來像你的編譯器有問題。

+0

我確實讓它在更新的編譯器上工作。由於我的情況,我可以升級編譯器。 – Harry 2009-02-22 22:32:51

1

這顯然不利於但代碼看起來和運行如預期的我。一切似乎都很好。

2

要添加到審批的合唱,這工作得很好,我(OS X Leopard的使用gcc)。

出於好奇,你需要使用-lm標誌?我沒有第一次,我第二次做了,沒有什麼區別,但這是因爲libm.dylib和libc.dylib是OS X上同一個庫的符號鏈接。也許你的libm被破壞了?你需要鏈接到libm嗎?我會認爲math.h函數是libc的一部分...?

編輯:

你做任何在此之前,請嘗試使用這個:

float f = 0; 
double d = 0; 

我不認爲應該改變什麼,但如果這樣做,我贏了。

2

一多「的作品在我的機器」在Ubuntu上用gcc 4.3.2版。

$ ./a.out 
1.000000 
1.000000 

雖然我在編譯時遇到了一些警告。

$ gcc -lm round.c 
round.c: In function ‘main’: 
round.c:11: warning: incompatible implicit declaration of built-in function ‘roundf’ 
round.c:12: warning: incompatible implicit declaration of built-in function ‘round’ 
0

看起來你使用得很好,描述一下你的環境?

2

litb在正確的軌道上。 -std=c99沒有工作,但加入#define _ISOC99_SOURCE工作。所以代碼如下所示:

#define _ISOC99_SOURCE 
#include <stdio.h> 
#include <math.h> 

int main(void) 
{ 
...