Je n'arrête pas de tomber sur les spécificateurs de format pour la famille de fonctions printf (). Ce que je veux, c'est pouvoir imprimer un double (ou flottant) avec un nombre maximum de chiffres donné après la virgule décimale. Si j'utilise:
printf("%1.3f", 359.01335);
printf("%1.3f", 359.00999);
Je reçois
359.013
359.010
Au lieu du désir
359.013
359.01
Quelqu'un peut-il m'aider?
Réponses:
Cela ne peut pas être fait avec les
printf
spécificateurs de format normaux . Le plus proche que vous pourriez obtenir serait:mais le ".6" est la largeur numérique totale, donc
le casse.
Ce que vous pouvez faire est de placer
sprintf("%.20g")
le nombre dans un tampon de chaîne, puis de manipuler la chaîne pour n'avoir que N caractères après la virgule décimale.En supposant que votre nombre se trouve dans la variable num, la fonction suivante supprimera toutes les
N
décimales sauf les premières , puis supprimera les zéros de fin (et le point décimal s'ils étaient tous des zéros).Si vous n'êtes pas satisfait de l'aspect troncature (qui tournerait
0.12399
en au0.123
lieu d'arrondir à0.124
), vous pouvez réellement utiliser les installations déjà fournies par arrondissementprintf
. Il vous suffit d'analyser le nombre au préalable pour créer dynamiquement les largeurs, puis de les utiliser pour transformer le nombre en chaîne:L'intérêt de
nDecimals()
dans ce cas est de calculer correctement les largeurs de champ, puis de formater le nombre en utilisant une chaîne de format basée sur cela. Le harnais de testmain()
montre cela en action:Une fois que vous avez la valeur correctement arrondie, vous pouvez à nouveau la passer à
morphNumericString()
pour supprimer les zéros de fin en modifiant simplement:dans:
(ou appeler
morphNumericString
à la fin denDecimals
mais, dans ce cas, je combinerais probablement les deux en une seule fonction), et vous vous retrouverez avec:la source
.
dans certains paramètres régionaux, la décimale est en fait une,
virgule.atof
restituiez la même valeur.0.10000000000000000555
sera une0.1
fois supprimé. Le problème peut survenir si vous avez une valeur légèrement inférieure, par exemple si la représentation la plus proche de42.1
était42.099999999314159
. Si vous vouliez vraiment gérer cela, vous auriez probablement besoin d'arrondir en fonction du dernier chiffre supprimé plutôt que de tronquer.printf
fonctions semblables car elles prennent déjà en charge les paramètres dynamiques (*
caractère spécial): par exemple,printf("%*.*f", total, decimals, x);
génère un nombre avec la longueur totale du champ et les décimales spécifiées dynamiquement.Pour supprimer les zéros de fin, vous devez utiliser le format "% g":
Une fois la question clarifiée un peu, la suppression des zéros n'est pas la seule chose qui a été posée, mais la limitation de la sortie à trois décimales était également nécessaire. Je pense que cela ne peut pas être fait avec des chaînes au format sprintf seules. Comme Pax Diablo l'a souligné, une manipulation des cordes serait nécessaire.
la source
J'aime la réponse de R. légèrement modifiée:
«1000» détermine la précision.
Puissance à l'arrondi 0,5.
ÉDITER
Ok, cette réponse a été éditée plusieurs fois et j'ai perdu la trace de ce à quoi je pensais il y a quelques années (et à l'origine elle ne remplissait pas tous les critères). Voici donc une nouvelle version (qui remplit tous les critères et gère correctement les nombres négatifs):
Et les cas de test:
Et la sortie des tests:
Désormais, tous les critères sont remplis:
Malheureusement, cette réponse est une double ligne car
sprintf
elle ne renvoie pas la chaîne.la source
Je recherche dans la chaîne (commençant à l'extrême droite) le premier caractère de la plage
1
jusqu'à9
(valeur ASCII49
-57
) puisnull
(défini sur0
) chaque caractère à droite - voir ci-dessous:la source
Qu'en est-il de quelque chose comme ça (peut avoir des erreurs d'arrondi et des problèmes de valeur négative qui nécessitent un débogage, laissés comme exercice pour le lecteur):
C'est légèrement programmatique mais au moins cela ne vous oblige pas à manipuler des chaînes.
la source
Une solution simple mais qui fait le travail, attribue une longueur et une précision connues et évite le risque de passer au format exponentiel (ce qui est un risque lorsque vous utilisez% g):
Ajoutez ou supprimez "elses" si vous voulez un maximum de 2 décimales; 4 décimales; etc.
Par exemple si vous vouliez 2 décimales:
Si vous souhaitez spécifier la largeur minimale pour que les champs restent alignés, incrémentez si nécessaire, par exemple:
Vous pouvez également convertir cela en une fonction dans laquelle vous transmettez la largeur souhaitée du champ:
la source
d = 0.0001
: alorsfloor(d)
est0
, donc la différence est plus grande que 0,000001, doncDoubleEquals
est faux, donc il n'utilisera pas le"%.0f"
spécificateur: vous verrez des zéros à la fin de"%*.2f"
ou"%*.3f"
. Cela ne répond donc pas à la question.J'ai trouvé des problèmes dans certaines des solutions affichées. J'ai mis cela en fonction des réponses ci-dessus. Il semble fonctionner pour moi.
la source
Certaines des solutions les plus votées suggèrent le
%g
spécificateur de conversion deprintf
. C'est faux car il y a des cas où%g
produira une notation scientifique. D'autres solutions utilisent les mathématiques pour imprimer le nombre souhaité de chiffres décimaux.Je pense que la solution la plus simple est d'utiliser
sprintf
avec le%f
spécificateur de conversion et de supprimer manuellement les zéros de fin et éventuellement un point décimal du résultat. Voici une solution C99:Notez que les caractères utilisés pour les chiffres et le séparateur décimal dépendent des paramètres régionaux actuels. Le code ci-dessus suppose un langage C ou anglais américain.
la source
Voici mon premier essai de réponse:
Bogues connus: Dépassement de tampon possible selon le format. Si "." est présent pour une raison autre que% f un mauvais résultat peut se produire.
la source
Pourquoi ne pas faire ça?
la source
Légère variation sur ci-dessus:
Code ici:
Il a encore un potentiel de débordement, alors soyez prudent; P
la source
Je dirais que vous devriez utiliser
printf("%.8g",value);
Si vous utilisez,
"%.6g"
vous n'obtiendrez pas la sortie souhaitée pour certains nombres comme 32.230210, il devrait imprimer32.23021
mais il s'imprime32.2302
la source
Votre code est arrondi à trois décimales en raison du ".3" avant le f
Ainsi, si la deuxième ligne est arrondie à deux décimales, vous devez la changer comme suit:
Ce code affichera les résultats souhaités:
* Notez que cela suppose que vous l'avez déjà imprimé sur des lignes séparées, sinon, les éléments suivants l'empêcheront d'imprimer sur la même ligne:
Le code source du programme suivant a été mon test pour cette réponse
la source