2013-01-24 73 views
1

本來我是使用下面的代碼使用的sprintf花車總是有2位小數:用sprintf格式化不帶小數位浮動,如果整數

static void MyFunc(char* buffer, const float percentage) 
{ 
    sprintf(buffer, "%.2f", percentage); 
} 

一個傳遞是0x419FFFFF 20的百分比值(調試視圖),這將20.00打印到緩衝區中。

我想反而在不是整數時顯示2個小數位,例如,

94.74 displayed as 94.74 
94.7 displayed as 94.70 
0  displayed as 0 
5  displayed as 5 
100 displayed as 100 

我目前使用以下代碼:

static void MyFunc(char* buffer, const float percentage) 
{ 
    int fractional_part = ((percentage - (int)percentage) * 100); 
    if (0 == fractional_part) 
    { 
     sprintf(buffer, "%d", (int)percentage); 
    } 
    else 
    { 
     sprintf(buffer, "%.2f", percentage); 
    } 
} 

現在,如果0x419FFFFF 20(調試器視圖)被傳遞,小數部分被計算爲99。我假定然後FRACTIONAL_PART總和最終被(19.99 - 19)* 100 = 99.那麼爲什麼第一個例子不將19.99打印到緩衝區?

什麼是我的問題的正確解決方案?

+2

的可能重複[只顯示小數點如果浮點組件不.00的sprintf/printf的(HTTP ://stackoverflow.com/questions/838064/only-show-decimal-point-if-floating-point-component-is-not-00-sprintf-printf) – unwind

+0

使用「%g」而不是「%d」作爲在上面的鏈接中指出 – MOHAMED

+0

@MohamedKALLEL這就是所謂的解開線程所暗示的。在我看來,它確實是一個重複。 – junix

回答

3

這是一個近似問題。

假設百分比是19.999。然後fractional_part將是99,並且浮點分支將被調用。

但打印19.999有兩位小數將它舍入到20.00,是什麼打印。

您可以隨時使用浮點分支,以獲得一致的結果,然後在'。'處截斷。如果它出來'.00'。否則,你冒着你的測試和printf的內部結構在一段時間內不一致。

#include <stdio.h> 
#include <string.h> 

int main(int argc, char **argv) 
{ 
     float percentage = 19.999; 
     char buffer[50]; 

     for (percentage = 19.990; percentage < 20.001; percentage += 0.001) 
     { 
       sprintf(buffer, "%.2f", percentage); 
       char *p = strstr(buffer, ".00"); 
       if (p) *p = 0x0; 
       printf("%.3f rendered as %.2f and becomes %s\n", percentage, percentage, buffer); 
     } 
     return 0; 
} 

19.990 rendered as 19.99 and becomes 19.99 
19.991 rendered as 19.99 and becomes 19.99 
19.992 rendered as 19.99 and becomes 19.99 
19.993 rendered as 19.99 and becomes 19.99 
19.994 rendered as 19.99 and becomes 19.99 
19.995 rendered as 19.99 and becomes 19.99 
19.996 rendered as 20.00 and becomes 20 
19.997 rendered as 20.00 and becomes 20 
19.998 rendered as 20.00 and becomes 20 
19.999 rendered as 20.00 and becomes 20 
20.000 rendered as 20.00 and becomes 20 
20.001 rendered as 20.00 and becomes 20 

如果你不printf的四捨五入戰略達成一致,只需要使用上round()(副本)percentage,迫使你自己。或者你也可以,例如,sprintf()三位數字,並刪除第三個。

而且在特定情況下(請注意我的系統(Linux的x86_64的)如何呈現0x419FFFFF):

#include <stdio.h> 
#include <string.h> 
#include <stdint.h> 

int main(int argc, char **argv) 
{ 
     float percentage = 3.1415; 
     char buffer[50]; 

     ((uint32_t *)(&percentage))[0] = 0x419FFFFF; 

     sprintf(buffer, "%.2f", percentage); 
     char *p = strstr(buffer, ".00"); 
     if (p) *p = 0x0; 
     printf("%.15f rendered as %.2f and becomes %s\n", percentage, percentage, buffer); 
     return 0; 
} 


19.999998092651367 rendered as 20.00 and becomes 20 
+0

這種方法效果很好,在代碼中很好,很簡單:) – integra753

0

而不是自己計算小數部分,您可以嘗試使用ceilf(f) == ffloorf(f) == f,如果f是整數,則返回true。 另一種替代方法是使用std lib中的modf (float x, float *ipart)或數學中的fmod

+0

這樣做我的調試器給百分比= 0x419FFFFF(20),ceilf(百分比)= 0x41A00000(20),floorf(百分比)= 0x41980000(19)。這些都不等於原來的百分比。 – integra753

+0

這些都不等於原來的百分比,所以我的代碼執行浮動路徑並打印20.00%,這正是我想要避免的。 – integra753

相關問題