Ini tidak dapat dilakukan dengan penentu printfformat normal . Yang paling dekat yang bisa Anda dapatkan adalah:
printf("%.6g", 359.013); // 359.013
printf("%.6g", 359.01); // 359.01
tapi ".6" adalah lebar numerik total jadi
printf("%.6g", 3.01357); // 3.01357
hancurkan.
Apa yang dapat Anda lakukan adalah sprintf("%.20g")memberikan nomor ke buffer string kemudian memanipulasi string tersebut agar hanya memiliki karakter N setelah titik desimal.
Dengan asumsi bilangan Anda ada di variabel num, fungsi berikut akan menghapus semua kecuali Ndesimal pertama , lalu menghapus angka nol yang tertinggal (dan titik desimal jika semuanya nol).
char str[50];
sprintf (str,"%.20g",num); // Make the number.
morphNumericString (str, 3);
: :
void morphNumericString (char *s, int n) {
char *p;
int count;
p = strchr (s,'.'); // Find decimal point, if any.
if (p != NULL) {
count = n; // Adjust for more or less decimals.
while (count >= 0) { // Maximum decimals allowed.
count--;
if (*p == '\0') // If there's less than desired.
break;
p++; // Next character.
}
*p-- = '\0'; // Truncate string.
while (*p == '0') // Remove trailing zeros.
*p-- = '\0';
if (*p == '.') { // If all decimals were zeros, remove ".".
*p = '\0';
}
}
}
Jika Anda tidak senang dengan aspek pemotongan (yang akan berubah 0.12399menjadi 0.123daripada membulatkannya 0.124), Anda sebenarnya dapat menggunakan fasilitas pembulatan yang sudah disediakan oleh printf. Anda hanya perlu menganalisis angka sebelumnya untuk membuat lebar secara dinamis, lalu gunakan angka tersebut untuk mengubah angka menjadi string:
#include <stdio.h>
void nDecimals (char *s, double d, int n) {
int sz; double d2;
// Allow for negative.
d2 = (d >= 0) ? d : -d;
sz = (d >= 0) ? 0 : 1;
// Add one for each whole digit (0.xx special case).
if (d2 < 1) sz++;
while (d2 >= 1) { d2 /= 10.0; sz++; }
// Adjust for decimal point and fractionals.
sz += 1 + n;
// Create format string then use it.
sprintf (s, "%*.*f", sz, n, d);
}
int main (void) {
char str[50];
double num[] = { 40, 359.01335, -359.00999,
359.01, 3.01357, 0.111111111, 1.1223344 };
for (int i = 0; i < sizeof(num)/sizeof(*num); i++) {
nDecimals (str, num[i], 3);
printf ("%30.20f -> %s\n", num[i], str);
}
return 0;
}
Inti dari nDecimals()kasus ini adalah untuk menghitung lebar bidang dengan benar, lalu memformat angka menggunakan format string berdasarkan itu. Harness uji main()menunjukkan ini dalam tindakan:
40.00000000000000000000 -> 40.000
359.01335000000000263753 -> 359.013
-359.00999000000001615263 -> -359.010
359.00999999999999090505 -> 359.010
3.01357000000000008200 -> 3.014
0.11111111099999999852 -> 0.111
1.12233439999999995429 -> 1.122
Setelah Anda memiliki nilai yang dibulatkan dengan benar, Anda dapat sekali lagi meneruskannya ke morphNumericString()untuk menghapus nol di belakang hanya dengan mengubah:
nDecimals (str, num[i], 3);
ke:
nDecimals (str, num[i], 3);
morphNumericString (str, 3);
(atau memanggil morphNumericStringdi akhir nDecimalstapi, dalam hal ini, saya mungkin hanya menggabungkan keduanya menjadi satu fungsi), dan Anda berakhir dengan:
40.00000000000000000000 -> 40
359.01335000000000263753 -> 359.013
-359.00999000000001615263 -> -359.01
359.00999999999999090505 -> 359.01
3.01357000000000008200 -> 3.014
0.11111111099999999852 -> 0.111
1.12233439999999995429 -> 1.122