Dies ist mit den normalen printf
Formatspezifizierern nicht möglich. Das nächste, was Sie bekommen könnten, wäre:
printf("%.6g", 359.013); // 359.013
printf("%.6g", 359.01); // 359.01
aber die ".6" ist also die gesamte numerische Breite
printf("%.6g", 3.01357); // 3.01357
bricht es.
Was Sie können tun , ist auf sprintf("%.20g")
die Zahl in einen String - Puffer dann die Zeichenfolge manipulieren , um nur haben N Zeichen hinter dem Komma.
Angenommen, Ihre Zahl befindet sich in der Variablen num, entfernt die folgende Funktion alle bis auf die ersten N
Dezimalstellen und entfernt dann die nachfolgenden Nullen (und den Dezimalpunkt, wenn sie alle Nullen waren).
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';
}
}
}
Wenn Sie nicht zufrieden mit dem Abschneiden Aspekte sind (was machen würde 0.12399
in 0.123
sie eher als Rundung 0.124
), können Sie tatsächlich die Rundung Einrichtungen bereits zur Verfügung gestellt nutzen printf
. Sie müssen nur die Zahl vorher analysieren, um die Breiten dynamisch zu erstellen, und diese dann verwenden, um die Zahl in eine Zeichenfolge umzuwandeln:
#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;
}
In nDecimals()
diesem Fall geht es darum, die Feldbreiten korrekt zu berechnen und die Zahl dann mit einer darauf basierenden Formatzeichenfolge zu formatieren. Das Testkabel main()
zeigt dies in Aktion:
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
Sobald Sie den korrekt gerundeten Wert haben, können Sie diesen erneut übergeben, morphNumericString()
um nachfolgende Nullen zu entfernen, indem Sie einfach Folgendes ändern:
nDecimals (str, num[i], 3);
in:
nDecimals (str, num[i], 3);
morphNumericString (str, 3);
(oder morphNumericString
am Ende aufrufen, nDecimals
aber in diesem Fall würde ich die beiden wahrscheinlich nur zu einer Funktion kombinieren), und am Ende erhalten Sie:
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