[英]Get printf to print all float digits
我對printf("%f", M_PI)
的行為感到困惑。 它打印出3.141593
,但M_PI
是3.14159265358979323846264338327950288
。 為什么printf會這樣做,如何讓它打印出整個浮動。 我知道%1.2f
格式說明符,但如果我使用它們,那么我得到一堆未使用的0,輸出很難看。 我想要浮子的整個精度,但不是額外的任何東西。
為什么printf會這樣做,如何讓它打印出整個浮動。
默認情況下, printf()
函數對%f
和%F
格式說明符的精度為6
。 從C11(N1570) §7.21.6.1/p8
fprintf函數 (強調我的前進):
如果缺少精度, 則取6 ; 如果精度為零且未指定#flag,則不顯示小數點字符。 如果出現小數點字符,則在其前面至少出現一個數字。 該值四舍五入到適當的位數。
因此,呼叫等同於:
printf("%.6f", M_PI);
這與“整個浮動”完全不同,至少不像你想象的那樣直接。 double
對象可能以二進制IEEE-754雙精度表示形式存儲。 您可以使用%a
或%A
格式說明符查看確切的表示形式,將其打印為十六進制浮點數。 例如:
printf("%a", M_PI);
將其輸出為:
0x1.921fb54442d18p+1
你可以認為它是“整個浮動”。
如果您需要的是“最長十進制近似”,那么這是有意義的,然后使用<float.h>
標頭中的DBL_DIG
。 C11 5.2.4.2.2 / p11 浮動類型的特征 :
小數位數q,使得帶有q個十進制數字的任何浮點數可以舍入為 p基數為b 的浮點數 ,然后再返回而不更改為q個十進制數字
例如:
printf("%.*f", DBL_DIG-1, M_PI);
可以打印:
3.14159265358979
您可以使用sprintf
將sprintf
打印到具有過度顯示精度的字符串,然后使用函數修剪0s,然后使用%s
將字符串傳遞給printf
以顯示它。 概念證明:
#include <math.h>
#include <string.h>
#include <stdio.h>
void trim_zeros(char *x){
int i;
i = strlen(x)-1;
while(i > 0 && x[i] == '0') x[i--] = '\0';
}
int main(void){
char s1[100];
char s2[100];
sprintf(s1,"%1.20f",23.01);
sprintf(s2,"%1.20f",M_PI);
trim_zeros(s1);
trim_zeros(s2);
printf("s1 = %s, s2 = %s\n",s1,s2);
//vs:
printf("s1 = %1.20f, s2 = %1.20f\n",23.01,M_PI);
return 0;
}
輸出:
s1 = 23.010000000000002, s2 = 3.1415926535897931
s1 = 23.01000000000000200000, s2 = 3.14159265358979310000
這表明這種方法可能不是你想要的。 如果小數部分中的連續零的數量超過一定長度(可以作為參數傳遞給trim_zeros
而不是簡單地修剪零,您可能希望截斷。另外 - 您可能希望確保23.0顯示為23.0而不是23.(所以也許在小數點后保留一個零)。這主要是概念證明 - 如果你對printf
使用sprintf
不滿意,那么按摩結果。
將一段文本轉換為浮點數或雙精度數后,“全部”數字不再是有意義的概念。 例如,計算機無法知道它轉換為“3.14”或“3.14000000000000000275”,並且它們都碰巧產生了相同的浮點數。 根據您對所涉及數字精確度的了解,您只需選擇適合您任務的位數即可。
如果要打印盡可能多的數字,可能會被格式清楚地表示,浮點數約為7位數,雙數約為15,但這是近似值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.