Comment imprimer un nombre avec des virgules comme séparateurs de milliers?


754

J'essaie d'imprimer un entier en Python 2.6.1 avec des virgules comme milliers de séparateurs. Par exemple, je veux montrer le nombre 1234567comme 1,234,567. Comment pourrais-je procéder? J'ai vu de nombreux exemples sur Google, mais je cherche le moyen pratique le plus simple.

Il n'est pas nécessaire qu'il soit spécifique aux paramètres régionaux pour choisir entre les périodes et les virgules. Je préférerais quelque chose d'aussi simple que raisonnablement possible.

Réponses:


1739

Paramètres régionaux ignorés

'{:,}'.format(value)  # For Python ≥2.7
f'{value:,}'  # For Python ≥3.6

Connaissance des paramètres régionaux

import locale
locale.setlocale(locale.LC_ALL, '')  # Use '' for auto, or force e.g. to 'en_US.UTF-8'

'{:n}'.format(value)  # For Python ≥2.7
f'{value:n}'  # For Python ≥3.6

Référence

Par mini-langage de spécification de format ,

L' ','option signale l'utilisation d'une virgule pour un séparateur de milliers. Pour un séparateur prenant en compte les paramètres régionaux, utilisez 'n'plutôt le type de présentation entier.


25
Notez que cela ne sera pas correct en dehors des États-Unis et de quelques autres endroits, dans ce cas, le locale.format () choisi est la bonne réponse.
Gringo Suave

11
La forme d'argument du mot clé:{val:,}.format(val=val)
CivFan

11
Grand merci. Pour les montants en argent, avec 2 décimales - "{:,. 2f}". Format (valeur)
dlink

3
pour le Portugal où nous utilisons le point (.) comme séparateur uniquement: {:,} ". format (value) .replace (',', '.')

13
En python 3.6 et supérieur, les chaînes f ajoutent encore plus de commodité. Par exemplef"{2 ** 64 - 1:,}"
CJ Gaconnet

285

Je l'ai fait fonctionner:

>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'en_US')
'en_US'
>>> locale.format("%d", 1255000, grouping=True)
'1,255,000'

Bien sûr, vous n'avez pas besoin de prise en charge de l'internationalisation, mais c'est clair, concis et utilise une bibliothèque intégrée.

PS Ce "% d" est le formateur habituel de style%. Vous ne pouvez avoir qu'un seul formateur, mais cela peut être tout ce dont vous avez besoin en termes de largeur de champ et de paramètres de précision.

PPS Si vous ne pouvez pas vous rendre localeau travail, je suggère une version modifiée de la réponse de Mark:

def intWithCommas(x):
    if type(x) not in [type(0), type(0L)]:
        raise TypeError("Parameter must be an integer.")
    if x < 0:
        return '-' + intWithCommas(-x)
    result = ''
    while x >= 1000:
        x, r = divmod(x, 1000)
        result = ",%03d%s" % (r, result)
    return "%d%s" % (x, result)

La récursivité est utile pour le cas négatif, mais une récursivité par virgule me semble un peu excessive.


14
J'ai essayé votre code, et malheureusement, j'obtiens ceci: "locale.Error: paramètre de locale non pris en charge". : -s
Mark Byers

11
Mark: Si vous êtes sous Linux, vous voudrez peut-être regarder ce qui se trouve dans votre /etc/locale.gen, ou tout ce que votre glibc utilise pour construire ses paramètres régionaux. Vous pouvez également essayer "" en "," en_US.utf8 "," en_US.UTF-8 ", 'en_UK" (sp?), Etc. mikez: Il doit y avoir un livre: "Dr. PEP: Ou Comment j'ai appris à cesser de m'inquiéter et à aimer docs.python.org. " J'ai abandonné la mémorisation de toutes les bibliothèques autour de Python 1.5.6. Quant à localemoi, j'en utilise le moins possible.
Mike DeSimone

10
Vous pouvez utiliser '' pour setlocaleutiliser la valeur par défaut, qui, nous l'espérons, sera appropriée.
Mark Ransom

24
Essayez ceci: locale.setlocale (locale.LC_ALL, '') Cela a fonctionné pour moi
Nadia Alramli

1
Bien qu'intelligent, je n'aime pas les fonctions qui définissent les paramètres globaux ... Utiliser 'blah'.format () est la meilleure façon de procéder.
Cerin

132

Pour l'inefficacité et l'illisibilité, il est difficile de battre:

>>> import itertools
>>> s = '-1234567'
>>> ','.join(["%s%s%s" % (x[0], x[1] or '', x[2] or '') for x in itertools.izip_longest(s[::-1][::3], s[::-1][1::3], s[::-1][2::3])])[::-1].replace('-,','-')

171
A voté pour la méthode la plus inefficace et illisible pour répondre à cette question.
psytek

1
serait bien si au moins cela fonctionnait. essayez ce nombre "17371830" il devient "173.718.3.0" =)
holms

5
Périodes? Ce n'est même pas possible, Holms. Ce morceau d'ordure ignore totalement les paramètres régionaux. Je me demande comment vous avez obtenu ce résultat. Votre exemple produit pour moi «17, 371 830», comme prévu.
Kasey Kirkham

11
Pour en faire une fonction, je suggère: lambda x: (lambda s: ','.join(["%s%s%s" % (x[0], x[1] or '', x[2] or '') for x in itertools.izip_longest(s[::-1][::3], s[::-1][1::3], s[::-1][2::3])])[::-1].replace('-,','-'))(str(x))juste pour garder le thème de l'obscurcissement.
quantum

95

Voici le code de regroupement des paramètres régionaux après avoir supprimé les parties non pertinentes et nettoyé un peu:

(Ce qui suit ne fonctionne que pour les entiers)

def group(number):
    s = '%d' % number
    groups = []
    while s and s[-1].isdigit():
        groups.append(s[-3:])
        s = s[:-3]
    return s + ','.join(reversed(groups))

>>> group(-23432432434.34)
'-23,432,432,434'

Il y a déjà de bonnes réponses ici. Je veux juste ajouter ceci pour référence future. En python 2.7, il y aura un spécificateur de format pour le séparateur de milliers. Selon les documents python, cela fonctionne comme ceci

>>> '{:20,.2f}'.format(f)
'18,446,744,073,709,551,616.00'

En python3.1, vous pouvez faire la même chose comme ceci:

>>> format(1234567, ',d')
'1,234,567'

Oui, les moyens les plus difficiles sont principalement pour les gens sur les anciens Pythons, tels que ceux livrés avec RHEL et d'autres distributions de support à long terme.
Mike DeSimone

3
comment exprimer cela avec des chaînes de format? "%, d"% 1234567 ne fonctionne pas
Frédéric Bazin

93

Je suis surpris que personne n'ait mentionné que vous pouvez faire cela avec des chaînes f en Python 3.6 aussi simple que cela:

>>> num = 10000000
>>> print(f"{num:,}")
10,000,000

... où la partie après les deux-points est le spécificateur de format. La virgule est le caractère de séparation que vous souhaitez, donc f"{num:_}"utilise des traits de soulignement au lieu d'une virgule.

Cela équivaut à utiliser format(num, ",")pour les anciennes versions de python 3.


C'est plus facile que n'importe laquelle des réponses les plus votées et ne nécessite aucune importation supplémentaire.
Z4-tier il y a

39

Voici un remplacement d'expression régulière d'une ligne:

re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%d" % val)

Fonctionne uniquement pour les sorties intégrées:

import re
val = 1234567890
re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%d" % val)
# Returns: '1,234,567,890'

val = 1234567890.1234567890
# Returns: '1,234,567,890'

Ou pour les flottants de moins de 4 chiffres, remplacez le spécificateur de format par %.3f:

re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%.3f" % val)
# Returns: '1,234,567,890.123'

NB: ne fonctionne pas correctement avec plus de trois chiffres décimaux car il tentera de regrouper la partie décimale:

re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%.5f" % val)
# Returns: '1,234,567,890.12,346'

Comment ça fonctionne

Décomposons-le:

re.sub(pattern, repl, string)

pattern = \
    "(\d)           # Find one digit...
     (?=            # that is followed by...
         (\d{3})+   # one or more groups of three digits...
         (?!\d)     # which are not followed by any more digits.
     )",

repl = \
    r"\1,",         # Replace that one digit by itself, followed by a comma,
                    # and continue looking for more matches later in the string.
                    # (re.sub() replaces all matches it finds in the input)

string = \
    "%d" % val      # Format the string as a decimal to begin with

1
utilisez le mode verbeux et vous pouvez avoir des commentaires directement dans le code
Daniel Stracaboško

Impossible de remplacer le "(?! \ D)" par un "$"?
GL2014

28

C'est ce que je fais pour les flotteurs. Bien que, honnêtement, je ne sais pas pour quelles versions il fonctionne - j'utilise 2.7:

my_number = 4385893.382939491

my_string = '{:0,.2f}'.format(my_number)

Retours: 4385893,38

Mise à jour: j'ai récemment rencontré un problème avec ce format (je ne pouvais pas vous en dire la raison exacte), mais j'ai pu le corriger en supprimant 0:

my_string = '{:,.2f}'.format(my_number)

19

Vous pouvez aussi utiliser '{:n}'.format( value ) pour une représentation locale. Je pense que c'est le moyen le plus simple pour une solution locale.

Pour plus d'informations, recherchez thousandsdans Python DOC .

Pour la devise, vous pouvez utiliser locale.currency, en définissant le drapeau grouping:

Code

import locale

locale.setlocale( locale.LC_ALL, '' )
locale.currency( 1234567.89, grouping = True )

Production

'Portuguese_Brazil.1252'
'R$ 1.234.567,89'

14

Elargissant légèrement la réponse d'Ian Schneider:

Si vous souhaitez utiliser un séparateur de milliers personnalisé, la solution la plus simple est:

'{:,}'.format(value).replace(',', your_custom_thousands_separator)

Exemples

'{:,.2f}'.format(123456789.012345).replace(',', ' ')

Si vous voulez la représentation allemande comme ça, ça devient un peu plus compliqué:

('{:,.2f}'.format(123456789.012345)
          .replace(',', ' ')  # 'save' the thousands separators 
          .replace('.', ',')  # dot to comma
          .replace(' ', '.')) # thousand separators to dot

Légèrement plus court:'{:_.2f}'.format(12345.6789).replace('.', ',').replace('_', '.')
Tom Pohl

12

Je suis sûr qu'il doit y avoir une fonction de bibliothèque standard pour cela, mais c'était amusant d'essayer de l'écrire moi-même en utilisant la récursivité alors voici ce que j'ai trouvé:

def intToStringWithCommas(x):
    if type(x) is not int and type(x) is not long:
        raise TypeError("Not an integer!")
    if x < 0:
        return '-' + intToStringWithCommas(-x)
    elif x < 1000:
        return str(x)
    else:
        return intToStringWithCommas(x / 1000) + ',' + '%03d' % (x % 1000)

Cela dit, si quelqu'un d'autre trouve un moyen standard de le faire, vous devriez l'utiliser à la place.


Malheureusement, ne fonctionne pas dans tous les cas. intToStringWithCommas (1000.1) -> '1.0001,000'
Nadia Alramli

Il a spécifiquement dit des entiers et que cela devrait être aussi simple que possible, j'ai donc décidé de ne pas gérer les types de données autres que des entiers. Je l'ai également rendu explicite dans le nom de la fonction _int_ToStringWithCommas. Maintenant, j'ai également ajouté une augmentation pour le rendre plus clair.
Mark Byers

8

Des commentaires à la recette d' activation 498181, j'ai retravaillé ceci:

import re
def thous(x, sep=',', dot='.'):
    num, _, frac = str(x).partition(dot)
    num = re.sub(r'(\d{3})(?=\d)', r'\1'+sep, num[::-1])[::-1]
    if frac:
        num += dot + frac
    return num

Il utilise la fonction d'expressions régulières: lookahead ie(?=\d) à- pour s'assurer que seuls les groupes de trois chiffres qui ont un chiffre après eux obtiennent une virgule. Je dis «après» parce que la chaîne est inversée à ce stade.

[::-1] inverse simplement une chaîne.



7

Python 3

-

Entiers (sans décimale):

"{:,d}".format(1234567)

-

Flotteurs (avec décimale):

"{:,.2f}".format(1234567)

où le nombre avant f spécifie le nombre de décimales.

-

Prime

Fonction de démarrage rapide et sale pour le système de numérotation des lakhs / crores indiens (12, 34, 567):

https://stackoverflow.com/a/44832241/4928578


5

à partir de Python version 2.6, vous pouvez le faire:

def format_builtin(n):
    return format(n, ',')

Pour les versions Python <2.6 et juste pour votre information, voici 2 solutions manuelles, elles transforment les flottants en pouces mais les nombres négatifs fonctionnent correctement:

def format_number_using_lists(number):
    string = '%d' % number
    result_list = list(string)
    indexes = range(len(string))
    for index in indexes[::-3][1:]:
        if result_list[index] != '-':
            result_list.insert(index+1, ',')
    return ''.join(result_list)

quelques choses à noter ici:

  • cette ligne: string = '% d'% number convertit magnifiquement un nombre en une chaîne, il prend en charge les négatifs et il supprime les fractions des flottants, ce qui en fait des entiers;
  • cette tranche indexe [:: - 3] renvoie chaque troisième élément à partir de la fin, j'ai donc utilisé une autre tranche [1:] pour supprimer le tout dernier élément car je n'ai pas besoin d'une virgule après le dernier numéro;
  • cette condition si l [index]! = '-' est utilisé pour prendre en charge les nombres négatifs, n'insérez pas de virgule après le signe moins.

Et une version plus hardcore:

def format_number_using_generators_and_list_comprehensions(number):
    string = '%d' % number
    generator = reversed( 
        [
            value+',' if (index!=0 and value!='-' and index%3==0) else value
            for index,value in enumerate(reversed(string))
        ]
    )
    return ''.join(generator)

2

Je suis un débutant en Python, mais un programmeur expérimenté. J'ai Python 3.5, je peux donc simplement utiliser la virgule, mais c'est néanmoins un exercice de programmation intéressant. Prenons le cas d'un entier non signé. Le programme Python le plus lisible pour ajouter des milliers de séparateurs semble être:

def add_commas(instr):
    out = [instr[0]]
    for i in range(1, len(instr)):
        if (len(instr) - i) % 3 == 0:
            out.append(',')
        out.append(instr[i])
    return ''.join(out)

Il est également possible d'utiliser une liste de compréhension:

add_commas(instr):
    rng = reversed(range(1, len(instr) + (len(instr) - 1)//3 + 1))
    out = [',' if j%4 == 0 else instr[-(j - j//4)] for j in rng]
    return ''.join(out)

C'est plus court et pourrait être un doublure, mais vous devrez faire de la gymnastique mentale pour comprendre pourquoi cela fonctionne. Dans les deux cas, nous obtenons:

for i in range(1, 11):
    instr = '1234567890'[:i]
    print(instr, add_commas(instr))
1 1
12 12
123 123
1234 1,234
12345 12,345
123456 123,456
1234567 1,234,567
12345678 12,345,678
123456789 123,456,789
1234567890 1,234,567,890

La première version est le choix le plus judicieux, si vous voulez que le programme soit compris.


1

En voici un qui fonctionne aussi pour les flotteurs:

def float2comma(f):
    s = str(abs(f)) # Convert to a string
    decimalposition = s.find(".") # Look for decimal point
    if decimalposition == -1:
        decimalposition = len(s) # If no decimal, then just work from the end
    out = "" 
    for i in range(decimalposition+1, len(s)): # do the decimal
        if not (i-decimalposition-1) % 3 and i-decimalposition-1: out = out+","
        out = out+s[i]      
    if len(out):
        out = "."+out # add the decimal point if necessary
    for i in range(decimalposition-1,-1,-1): # working backwards from decimal point
        if not (decimalposition-i-1) % 3 and decimalposition-i-1: out = ","+out
        out = s[i]+out      
    if f < 0:
        out = "-"+out
    return out

Exemple d'utilisation:

>>> float2comma(10000.1111)
'10,000.111,1'
>>> float2comma(656565.122)
'656,565.122'
>>> float2comma(-656565.122)
'-656,565.122'

1
float2comma(12031023.1323)renvoie: '12, 031,023.132,3 '
demux

1

Un liner pour Python 2.5+ et Python 3 (int positif uniquement):

''.join(reversed([x + (',' if i and not i % 3 else '') for i, x in enumerate(reversed(str(1234567)))]))

1

Solution universelle

J'ai trouvé quelques problèmes avec le séparateur de points dans les réponses précédentes les plus votées. J'ai conçu une solution universelle où vous pouvez utiliser ce que vous voulez comme mille séparateurs sans modifier les paramètres régionaux . Je sais que ce n'est pas la solution la plus élégante, mais elle fait le travail. N'hésitez pas à l'améliorer!

def format_integer(number, thousand_separator='.'):
    def reverse(string):
        string = "".join(reversed(string))
        return string

    s = reverse(str(number))
    count = 0
    result = ''
    for char in s:
        count = count + 1
        if count % 3 == 0:
            if len(s) == count:
                result = char + result
            else:
                result = thousand_separator + char + result
        else:
            result = char + result
    return result


print(format_integer(50))
# 50
print(format_integer(500))
# 500
print(format_integer(50000))
# 50.000
print(format_integer(50000000))
# 50.000.000

0

Cela fait de l'argent avec les virgules

def format_money(money, presym='$', postsym=''):
    fmt = '%0.2f' % money
    dot = string.find(fmt, '.')
    ret = []
    if money < 0 :
        ret.append('(')
        p0 = 1
    else :
        p0 = 0
    ret.append(presym)
    p1 = (dot-p0) % 3 + p0
    while True :
        ret.append(fmt[p0:p1])
        if p1 == dot : break
        ret.append(',')
        p0 = p1
        p1 += 3
    ret.append(fmt[dot:])   # decimals
    ret.append(postsym)
    if money < 0 : ret.append(')')
    return ''.join(ret)

0

J'ai une version python 2 et python 3 de ce code. Je sais que la question a été posée pour python 2 mais maintenant (8 ans plus tard lol), les gens vont probablement utiliser python 3.

Code Python 3:

import random
number = str(random.randint(1, 10000000))
comma_placement = 4
print('The original number is: {}. '.format(number))
while True:
    if len(number) % 3 == 0:
        for i in range(0, len(number) // 3 - 1):
            number = number[0:len(number) - comma_placement + 1] + ',' + number[len(number) - comma_placement + 1:]
            comma_placement = comma_placement + 4
    else:
        for i in range(0, len(number) // 3):
            number = number[0:len(number) - comma_placement + 1] + ',' + number[len(number) - comma_placement + 1:]
    break
print('The new and improved number is: {}'.format(number))        


Code Python 2: (Modifier. Le code python 2 ne fonctionne pas. Je pense que la syntaxe est différente).

import random
number = str(random.randint(1, 10000000))
comma_placement = 4
print 'The original number is: %s.' % (number)
while True:
    if len(number) % 3 == 0:
        for i in range(0, len(number) // 3 - 1):
            number = number[0:len(number) - comma_placement + 1] + ',' + number[len(number) - comma_placement + 1:]
            comma_placement = comma_placement + 4
    else:
        for i in range(0, len(number) // 3):
            number = number[0:len(number) - comma_placement + 1] + ',' + number[len(number) - comma_placement + 1:]
    break
print 'The new and improved number is: %s.' % (number) 

0

J'utilise python 2.5, donc je n'ai pas accès au formatage intégré.

J'ai regardé le code Django intcomma (intcomma_recurs dans le code ci-dessous) et j'ai réalisé qu'il était inefficace, car il est récursif et la compilation de l'expression régulière à chaque exécution n'est pas non plus une bonne chose. Ce n'est pas nécessairement un «problème» car Django n'est pas vraiment CELA concentré sur ce type de performances de bas niveau. De plus, je m'attendais à un facteur de différence de performances de 10, mais ce n'est que 3 fois plus lent.

Par curiosité, j'ai implémenté quelques versions d'intcomma pour voir quels sont les avantages en termes de performances lors de l'utilisation de regex. Mes données de test concluent un léger avantage pour cette tâche, mais étonnamment pas grand-chose du tout.

J'ai également été heureux de voir ce que je soupçonnais: l'utilisation de l'approche xrange inverse n'est pas nécessaire dans le cas sans regex, mais cela rend le code légèrement meilleur au prix de ~ 10% de performances.

En outre, je suppose que ce que vous passez est une chaîne et ressemble un peu à un nombre. Résultats indéterminés autrement.

from __future__ import with_statement
from contextlib import contextmanager
import re,time

re_first_num = re.compile(r"\d")
def intcomma_noregex(value):
    end_offset, start_digit, period = len(value),re_first_num.search(value).start(),value.rfind('.')
    if period == -1:
        period=end_offset
    segments,_from_index,leftover = [],0,(period-start_digit) % 3
    for _index in xrange(start_digit+3 if not leftover else start_digit+leftover,period,3):
        segments.append(value[_from_index:_index])
        _from_index=_index
    if not segments:
        return value
    segments.append(value[_from_index:])
    return ','.join(segments)

def intcomma_noregex_reversed(value):
    end_offset, start_digit, period = len(value),re_first_num.search(value).start(),value.rfind('.')
    if period == -1:
        period=end_offset
    _from_index,segments = end_offset,[]
    for _index in xrange(period-3,start_digit,-3):
        segments.append(value[_index:_from_index])
        _from_index=_index
    if not segments:
        return value
    segments.append(value[:_from_index])
    return ','.join(reversed(segments))

re_3digits = re.compile(r'(?<=\d)\d{3}(?!\d)')
def intcomma(value):
    segments,last_endoffset=[],len(value)
    while last_endoffset > 3:
        digit_group = re_3digits.search(value,0,last_endoffset)
        if not digit_group:
            break
        segments.append(value[digit_group.start():last_endoffset])
        last_endoffset=digit_group.start()
    if not segments:
        return value
    if last_endoffset:
        segments.append(value[:last_endoffset])
    return ','.join(reversed(segments))

def intcomma_recurs(value):
    """
    Converts an integer to a string containing commas every three digits.
    For example, 3000 becomes '3,000' and 45000 becomes '45,000'.
    """
    new = re.sub("^(-?\d+)(\d{3})", '\g<1>,\g<2>', str(value))
    if value == new:
        return new
    else:
        return intcomma(new)

@contextmanager
def timed(save_time_func):
    begin=time.time()
    try:
        yield
    finally:
        save_time_func(time.time()-begin)

def testset_xsimple(func):
    func('5')

def testset_simple(func):
    func('567')

def testset_onecomma(func):
    func('567890')

def testset_complex(func):
    func('-1234567.024')

def testset_average(func):
    func('-1234567.024')
    func('567')
    func('5674')

if __name__ == '__main__':
    print 'Test results:'
    for test_data in ('5','567','1234','1234.56','-253892.045'):
        for func in (intcomma,intcomma_noregex,intcomma_noregex_reversed,intcomma_recurs):
            print func.__name__,test_data,func(test_data)
    times=[]
    def overhead(x):
        pass
    for test_run in xrange(1,4):
        for func in (intcomma,intcomma_noregex,intcomma_noregex_reversed,intcomma_recurs,overhead):
            for testset in (testset_xsimple,testset_simple,testset_onecomma,testset_complex,testset_average):
                for x in xrange(1000): # prime the test
                    testset(func)
                with timed(lambda x:times.append(((test_run,func,testset),x))):
                    for x in xrange(50000):
                        testset(func)
    for (test_run,func,testset),_delta in times:
        print test_run,func.__name__,testset.__name__,_delta

Et voici les résultats des tests:

intcomma 5 5
intcomma_noregex 5 5
intcomma_noregex_reversed 5 5
intcomma_recurs 5 5
intcomma 567 567
intcomma_noregex 567 567
intcomma_noregex_reversed 567 567
intcomma_recurs 567 567
intcomma 1234 1,234
intcomma_noregex 1234 1,234
intcomma_noregex_reversed 1234 1,234
intcomma_recurs 1234 1,234
intcomma 1234.56 1,234.56
intcomma_noregex 1234.56 1,234.56
intcomma_noregex_reversed 1234.56 1,234.56
intcomma_recurs 1234.56 1,234.56
intcomma -253892.045 -253,892.045
intcomma_noregex -253892.045 -253,892.045
intcomma_noregex_reversed -253892.045 -253,892.045
intcomma_recurs -253892.045 -253,892.045
1 intcomma testset_xsimple 0.0410001277924
1 intcomma testset_simple 0.0369999408722
1 intcomma testset_onecomma 0.213000059128
1 intcomma testset_complex 0.296000003815
1 intcomma testset_average 0.503000020981
1 intcomma_noregex testset_xsimple 0.134000062943
1 intcomma_noregex testset_simple 0.134999990463
1 intcomma_noregex testset_onecomma 0.190999984741
1 intcomma_noregex testset_complex 0.209000110626
1 intcomma_noregex testset_average 0.513000011444
1 intcomma_noregex_reversed testset_xsimple 0.124000072479
1 intcomma_noregex_reversed testset_simple 0.12700009346
1 intcomma_noregex_reversed testset_onecomma 0.230000019073
1 intcomma_noregex_reversed testset_complex 0.236999988556
1 intcomma_noregex_reversed testset_average 0.56299996376
1 intcomma_recurs testset_xsimple 0.348000049591
1 intcomma_recurs testset_simple 0.34600019455
1 intcomma_recurs testset_onecomma 0.625
1 intcomma_recurs testset_complex 0.773999929428
1 intcomma_recurs testset_average 1.6890001297
1 overhead testset_xsimple 0.0179998874664
1 overhead testset_simple 0.0190000534058
1 overhead testset_onecomma 0.0190000534058
1 overhead testset_complex 0.0190000534058
1 overhead testset_average 0.0309998989105
2 intcomma testset_xsimple 0.0360000133514
2 intcomma testset_simple 0.0369999408722
2 intcomma testset_onecomma 0.207999944687
2 intcomma testset_complex 0.302000045776
2 intcomma testset_average 0.523000001907
2 intcomma_noregex testset_xsimple 0.139999866486
2 intcomma_noregex testset_simple 0.141000032425
2 intcomma_noregex testset_onecomma 0.203999996185
2 intcomma_noregex testset_complex 0.200999975204
2 intcomma_noregex testset_average 0.523000001907
2 intcomma_noregex_reversed testset_xsimple 0.130000114441
2 intcomma_noregex_reversed testset_simple 0.129999876022
2 intcomma_noregex_reversed testset_onecomma 0.236000061035
2 intcomma_noregex_reversed testset_complex 0.241999864578
2 intcomma_noregex_reversed testset_average 0.582999944687
2 intcomma_recurs testset_xsimple 0.351000070572
2 intcomma_recurs testset_simple 0.352999925613
2 intcomma_recurs testset_onecomma 0.648999929428
2 intcomma_recurs testset_complex 0.808000087738
2 intcomma_recurs testset_average 1.81900000572
2 overhead testset_xsimple 0.0189998149872
2 overhead testset_simple 0.0189998149872
2 overhead testset_onecomma 0.0190000534058
2 overhead testset_complex 0.0179998874664
2 overhead testset_average 0.0299999713898
3 intcomma testset_xsimple 0.0360000133514
3 intcomma testset_simple 0.0360000133514
3 intcomma testset_onecomma 0.210000038147
3 intcomma testset_complex 0.305999994278
3 intcomma testset_average 0.493000030518
3 intcomma_noregex testset_xsimple 0.131999969482
3 intcomma_noregex testset_simple 0.136000156403
3 intcomma_noregex testset_onecomma 0.192999839783
3 intcomma_noregex testset_complex 0.202000141144
3 intcomma_noregex testset_average 0.509999990463
3 intcomma_noregex_reversed testset_xsimple 0.125999927521
3 intcomma_noregex_reversed testset_simple 0.126999855042
3 intcomma_noregex_reversed testset_onecomma 0.235999822617
3 intcomma_noregex_reversed testset_complex 0.243000030518
3 intcomma_noregex_reversed testset_average 0.56200003624
3 intcomma_recurs testset_xsimple 0.337000131607
3 intcomma_recurs testset_simple 0.342000007629
3 intcomma_recurs testset_onecomma 0.609999895096
3 intcomma_recurs testset_complex 0.75
3 intcomma_recurs testset_average 1.68300008774
3 overhead testset_xsimple 0.0189998149872
3 overhead testset_simple 0.018000125885
3 overhead testset_onecomma 0.018000125885
3 overhead testset_complex 0.0179998874664
3 overhead testset_average 0.0299999713898

Je pensais que la solution à un regex de Daniel Fortunov serait n ° 1 et battrait tous les algorithmes parce que le regex est tellement raffiné / optimisé et codé en C, mais non .. Je suppose que le modèle et l'anticipation sont trop chers. il tombe à environ le double du temps de l'intcomma ci-dessus, même avec la précompilation de l'expression régulière.
parity3


-1

Voici une autre variante utilisant une fonction de générateur qui fonctionne pour les entiers:

def ncomma(num):
    def _helper(num):
        # assert isinstance(numstr, basestring)
        numstr = '%d' % num
        for ii, digit in enumerate(reversed(numstr)):
            if ii and ii % 3 == 0 and digit.isdigit():
                yield ','
            yield digit

    return ''.join(reversed([n for n in _helper(num)]))

Et voici un test:

>>> for i in (0, 99, 999, 9999, 999999, 1000000, -1, -111, -1111, -111111, -1000000):
...     print i, ncomma(i)
... 
0 0
99 99
999 999
9999 9,999
999999 999,999
1000000 1,000,000
-1 -1
-111 -111
-1111 -1,111
-111111 -111,111
-1000000 -1,000,000

-1

Juste sous-classe long(ou float, ou autre). C'est très pratique, car de cette façon, vous pouvez toujours utiliser vos nombres dans les opérations mathématiques (et donc le code existant), mais ils s'imprimeront tous bien dans votre terminal.

>>> class number(long):

        def __init__(self, value):
            self = value

        def __repr__(self):
            s = str(self)
            l = [x for x in s if x in '1234567890']
            for x in reversed(range(len(s)-1)[::3]):
                l.insert(-x, ',')
            l = ''.join(l[1:])
            return ('-'+l if self < 0 else l) 

>>> number(-100000)
-100,000
>>> number(-100)
-100
>>> number(-12345)
-12,345
>>> number(928374)
928,374
>>> 345

8
J'aime l'idée de la sous-classe, mais est-ce __repr__()la bonne méthode pour remplacer? Je suggère de passer outre __str__()et de laisser __repr__()seul, car cela int(repr(number(928374)))devrait fonctionner, mais int()étouffera les virgules.
steveha

@steveha a un bon point, mais la justification aurait dû être que number(repr(number(928374)))cela ne fonctionne pas, non int(repr(number(928374))). Tout de même, pour que cette approche fonctionne directement avec print, comme l'OP l'a demandé, la __str__()méthode devrait être celle qui a été remplacée plutôt que __repr__(). Quoi qu'il en soit, il semble y avoir un bogue dans la logique d'insertion de virgule de base.
martineau

-1

Italie:

>>> import locale
>>> locale.setlocale(locale.LC_ALL,"")
'Italian_Italy.1252'
>>> f"{1000:n}"
'1.000'

-8

Pour les flotteurs:

float(filter(lambda x: x!=',', '1,234.52'))
# returns 1234.52

Pour les pouces:

int(filter(lambda x: x!=',', '1,234'))
# returns 1234

5
Cela supprime les virgules. Bien que pratique, le PO a demandé un moyen de les ajouter . De plus, quelque chose comme ça float('1,234.52'.translate(None, ','))pourrait être plus simple et peut-être plus rapide.
pause jusqu'à nouvel ordre.
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.