Je veux supprimer des chiffres d'un flottant pour avoir un nombre fixe de chiffres après le point, comme:
1.923328437452 -> 1.923
J'ai besoin de sortir sous forme de chaîne vers une autre fonction, pas d'imprimer.
Je veux aussi ignorer les chiffres perdus, pas les arrondir.
python
floating-point
Joan Venge
la source
la source
Réponses:
Tout d'abord, la fonction, pour ceux qui veulent juste du code copier-coller:
Ceci est valable dans Python 2.7 et 3.1+. Pour les versions plus anciennes, il n'est pas possible d'obtenir le même effet «d'arrondi intelligent» (du moins, non sans beaucoup de code compliqué), mais arrondir à 12 décimales avant la troncature fonctionnera la plupart du temps:
Explication
Le cœur de la méthode sous-jacente consiste à convertir la valeur en une chaîne avec une précision maximale, puis à couper tout ce qui dépasse le nombre de caractères souhaité. La dernière étape est facile; cela peut être fait soit avec une manipulation de chaîne
ou le
decimal
moduleLa première étape, la conversion en chaîne, est assez difficile car il existe des paires de littéraux à virgule flottante (c'est-à-dire ce que vous écrivez dans le code source) qui produisent à la fois la même représentation binaire et qui doivent cependant être tronquées différemment. Par exemple, considérons 0,3 et 0,29999999999999998. Si vous écrivez
0.3
dans un programme Python, le compilateur l'encode en utilisant le format à virgule flottante IEEE dans la séquence de bits (en supposant un flottant de 64 bits)Il s'agit de la valeur la plus proche de 0,3 qui peut être représentée avec précision par un flottant IEEE. Mais si vous écrivez
0.29999999999999998
dans un programme Python, le compilateur le traduit exactement dans la même valeur . Dans un cas, vous vouliez qu'il soit tronqué (à un chiffre) comme0.3
, alors que dans l'autre cas, vous vouliez qu'il soit tronqué comme0.2
, mais Python ne peut donner qu'une seule réponse. C'est une limitation fondamentale de Python, ou en fait de tout langage de programmation sans évaluation paresseuse. La fonction de troncature n'a accès qu'à la valeur binaire stockée dans la mémoire de l'ordinateur, et non à la chaîne que vous avez réellement tapée dans le code source. 1Si vous décodez la séquence de bits en un nombre décimal, à nouveau en utilisant le format à virgule flottante IEEE 64 bits, vous obtenez
donc une implémentation naïve arriverait
0.2
même si ce n'est probablement pas ce que vous voulez. Pour plus d'informations sur l'erreur de représentation en virgule flottante, consultez le didacticiel Python .Il est très rare de travailler avec une valeur à virgule flottante qui est si proche d'un nombre rond et qui n'est pas intentionnellement égale à ce nombre rond. Ainsi, lors de la troncature, il est probablement logique de choisir la "plus belle" représentation décimale parmi tout ce qui pourrait correspondre à la valeur en mémoire. Python 2.7 et plus (mais pas 3.0) inclut un algorithme sophistiqué pour faire exactement cela , auquel nous pouvons accéder via l'opération de formatage de chaîne par défaut.
La seule mise en garde est que cela agit comme une
g
spécification de format, dans le sens où il utilise la notation exponentielle (1.23e+4
) si le nombre est suffisamment grand ou petit. La méthode doit donc saisir ce cas et le gérer différemment. Il y a quelques cas où l'utilisation d'unef
spécification de format à la place pose un problème, comme essayer de tronquer3e-10
à 28 chiffres de précision (cela produit0.0000000002999999999999999980
), et je ne suis pas encore sûr de la meilleure façon de les gérer.Si vous réellement êtes travaillez avec
float
s qui sont très proches de chiffres ronds , mais intentionnellement ne les égale à (comme ,29999999999999998 ou 99,959999999999994), cela produira des faux positifs, à savoir qu'il y aura des chiffres ronds que vous ne vouliez pas arrondi. Dans ce cas, la solution est de spécifier une précision fixe.Le nombre de chiffres de précision à utiliser ici n'a pas vraiment d'importance, il doit seulement être suffisamment grand pour s'assurer que tout arrondi effectué dans la conversion de chaîne ne "augmente" pas la valeur à sa belle représentation décimale. Je pense que cela
sys.float_info.dig + n + 2
peut suffire dans tous les cas, mais sinon, il faudra2
peut-être augmenter ce montant, et cela ne fait pas de mal de le faire.Dans les versions antérieures de Python (jusqu'à 2.6 ou 3.0), le formatage des nombres à virgule flottante était beaucoup plus grossier et produisait régulièrement des choses comme
Si tel est votre cas, si vous ne voulez utiliser des représentations décimales « BELLES » pour tronquer, tout ce que vous pouvez faire (pour autant que je sache) est de choisir un certain nombre de chiffres, moins représentable pleine de précision par un
float
, et autour de la nombre à autant de chiffres avant de le tronquer. Un choix typique est 12,mais vous pouvez l'ajuster en fonction des nombres que vous utilisez.
1 Eh bien ... j'ai menti. Techniquement, vous pouvez demander à Python de ré-analyser son propre code source et d'extraire la partie correspondant au premier argument que vous passez à la fonction de troncature. Si cet argument est un littéral à virgule flottante, vous pouvez simplement le couper un certain nombre de places après la virgule décimale et le renvoyer. Cependant, cette stratégie ne fonctionne pas si l'argument est une variable, ce qui la rend assez inutile. Ce qui suit est présenté à titre de divertissement uniquement:
Généraliser cela pour gérer le cas où vous passez une variable semble être une cause perdue, car vous devrez remonter en arrière tout au long de l'exécution du programme jusqu'à ce que vous trouviez le littéral à virgule flottante qui a donné sa valeur à la variable. S'il y en a même un. La plupart des variables seront initialisées à partir de l'entrée utilisateur ou d'expressions mathématiques, auquel cas la représentation binaire est tout ce qu'il y a.
la source
applymap()
). Il y a peut-être un moyen de rendre l'opération dans son ensemble plus efficace, mais ce serait une question distincte.Consultez la documentation de Python sur les types standard . Vous devrez faire défiler un peu vers le bas pour accéder à la fonction ronde. Essentiellement, le deuxième nombre indique le nombre de décimales à arrondir.
la source
Le résultat de
round
est un flottant, alors faites attention (l'exemple provient de Python 2.6):Vous serez mieux avec une chaîne formatée:
la source
round(1.23456, 3)
est1.235
et pas1.2350000000000001
la source
2
, vous aurez un point décimal.
à la fin de la chaîne - pas vraiment une bonne solution je pense.À mon invite Python 2.7:
>>> int(1.923328437452 * 1000)/1000.0 1.923
la source
Script python simple -
la source
Cela devrait fonctionner. Cela devrait vous donner la troncature que vous recherchez.
la source
La façon vraiment pythonique de le faire est
ou plus court:
Mettre à jour
Habituellement, le problème n'est pas dans la troncature des flottants lui-même, mais dans l'utilisation incorrecte des nombres flottants avant l' arrondi.
Par exemple:
int(0.7*3*100)/100 == 2.09
.Si vous êtes obligé d'utiliser des flottants (par exemple, vous accélérez votre code avec
numba
), il est préférable d'utiliser des cents comme "représentation interne" des prix: (70*3 == 210
) et de multiplier / diviser les entrées / sorties.la source
int(0.7*3*100)/100 == 2.09
. Où est passé mon 1 centime?ImportError: cannot import name 'D'
, je crois que vous vouliez faire une importation nommée non?Tant de réponses données à cette question sont complètement fausses. Ils arrondissent les flottants (plutôt que tronqués) ou ne fonctionnent pas dans tous les cas.
C'est le meilleur résultat de Google lorsque je recherche 'Python truncate float', un concept qui est vraiment simple et qui mérite de meilleures réponses. Je suis d'accord avec Hatchkins que l'utilisation du
decimal
module est la manière pythonique de faire cela, donc je donne ici une fonction qui, je pense, répond correctement à la question, et qui fonctionne comme prévu dans tous les cas.En remarque, les valeurs fractionnaires, en général, ne peuvent pas être représentées exactement par des variables binaires à virgule flottante (voir ici pour une discussion à ce sujet), c'est pourquoi ma fonction renvoie une chaîne.
la source
J'ai fait quelque chose comme ça:
la source
Tu peux faire:
essai:
la source
Si vous avez envie de mathémagique, cela fonctionne pour les nombres + cinq:
la source
Lors de l'utilisation d'un pandas df cela a fonctionné pour moi
la source
Je voulais juste mentionner que l’ancienne astuce "make round () with floor ()"
peut être retourné pour créer un sol () à partir de round ()
Bien que ces deux règles ne respectent pas les nombres négatifs, son utilisation est loin d'être idéale:
la source
int (16,5); cela donnera une valeur entière de 16, c'est-à-dire trunc, ne pourra pas spécifier de décimales, mais je suppose que vous pouvez le faire en
la source
Voici un moyen simple:
pour num = 1,923328437452, cela donne 1,923
la source
la source
Une fonction générale et simple à utiliser:
la source
Il existe une solution de contournement simple en python 3. Où couper J'ai défini avec une variable d'aide decPlace pour faciliter l'adaptation.
Production:
J'espère que ça aide.
la source
la source
Variante courte et facile
la source
La plupart des réponses sont beaucoup trop compliquées à mon avis, qu'en est-il de cela?
Recherche simplement l'index de «.» et tronquer à volonté (pas d'arrondi). Convertissez la chaîne en flottant comme étape finale.
Ou dans votre cas si vous obtenez un float en entrée et que vous voulez une chaîne en sortie:
la source
# diviser et multiplier par 10 ** nombre de chiffres souhaités
la source
utilisez numpy.round
la source
Quelque chose d'assez simple pour tenir dans une liste-compréhension, sans bibliothèques ou autres dépendances externes. Pour Python> = 3.6, il est très simple d'écrire avec des chaînes f.
L'idée est de laisser la conversion de chaîne faire l'arrondi à un endroit de plus que nécessaire , puis de couper le dernier chiffre.
Bien sûr, il y a un arrondi ici (à savoir pour le quatrième chiffre), mais l'arrondi à un moment donné est inévitable. Dans le cas où la transition entre la troncature et l'arrondi est pertinente, voici un exemple légèrement meilleur:
Bonus: supprimer les zéros à droite
la source
L'idée de base donnée ici me semble être la meilleure approche pour ce problème. Malheureusement, il a reçu moins de votes tandis que la dernière réponse qui a plus de votes n'est pas complète (comme observé dans les commentaires). Espérons que l'implémentation ci-dessous fournit une solution courte et complète pour la troncature .
qui devrait prendre soin de tous les cas de coin trouvés ici et ici .
la source
Suis aussi un débutant en python et après avoir utilisé quelques morceaux ici, j'offre mes deux cents
str (int (time.time ())) prendra le temps epoch comme int et le convertira en string et joindra avec ... str (datetime.now (). microsecond) [: 3] qui renvoie les microsecondes uniquement, convert chaîne et tronquer aux 3 premiers caractères
la source
la source
Si vous voulez dire lors de l'impression, alors ce qui suit devrait fonctionner:
la source