Bagaimana cara mencetak nomor dengan koma sebagai pemisah ribuan?

754

Saya mencoba untuk mencetak integer di Python 2.6.1 dengan koma sebagai pemisah ribuan. Sebagai contoh, saya ingin menunjukkan nomor tersebut 1234567sebagai 1,234,567. Bagaimana saya bisa melakukan ini? Saya telah melihat banyak contoh di Google, tetapi saya mencari cara praktis yang paling sederhana.

Tidak perlu spesifik lokal untuk memutuskan antara periode dan koma. Saya lebih suka sesuatu yang sesederhana mungkin.

Elias Zamaria
sumber

Jawaban:

1739

Lokal tidak sadar

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

Lokal sadar

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

Referensi

Per Format Spesifikasi Mini-Bahasa ,

The ','pilihan sinyal penggunaan koma untuk pemisah ribuan. Untuk pemisah sadar lokal, gunakan 'n'tipe presentasi integer sebagai gantinya.

Ian Schneider
sumber
25
Perhatikan bahwa ini tidak akan benar di luar AS dan beberapa tempat lain, dalam hal itu locale.format () yang dipilih adalah jawaban yang benar.
Gringo Suave
11
Bentuk argumen kata kunci:{val:,}.format(val=val)
CivFan
11
Terima kasih banyak. Untuk jumlah uang, dengan 2 tempat desimal - "{:,. 2f}". (Format)
dlink
3
untuk Portugal tempat kami menggunakan titik (.) sebagai pemisah, hanya: {:,} "
13
Dalam python 3.6 dan lebih tinggi, f-string menambah lebih banyak kenyamanan. Misalnyaf"{2 ** 64 - 1:,}"
CJ Gaconnet
285

Saya mendapatkan ini untuk bekerja:

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

Tentu, Anda tidak memerlukan dukungan internasionalisasi, tetapi jelas, ringkas, dan menggunakan perpustakaan bawaan.

PS Itu "% d" adalah formatter%-style biasa. Anda hanya dapat memiliki satu formatter, tetapi dapat berupa apa pun yang Anda perlukan dalam hal lebar bidang dan pengaturan presisi.

PPS Jika Anda tidak bisa mulai localebekerja, saya akan menyarankan versi modifikasi dari jawaban 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)

Rekursi berguna untuk kasus negatif, tetapi satu rekursi per koma tampaknya agak berlebihan bagi saya.

Mike DeSimone
sumber
14
Saya mencoba kode Anda, dan sayangnya, saya mendapatkan ini: "locale.Error: pengaturan lokal yang tidak didukung". : -s
Mark Byers
11
Mark: Jika Anda menggunakan Linux, Anda mungkin ingin melihat apa yang ada di /etc/locale.gen Anda, atau apa pun yang digunakan glibc Anda untuk membangun locales-nya. Anda mungkin juga ingin mencoba "" en "," en_US.utf8 "," en_US.UTF-8 ", 'en_UK" (sp?), Dll. Mikez: Perlu ada buku: "Dr. PEP: Atau Bagaimana Saya Belajar Menghentikan Khawatir dan Cinta docs.python.org. " Saya berhenti mengingat semua perpustakaan di sekitar Python 1.5.6. Adapun locale, saya menggunakan sesedikit mungkin.
Mike DeSimone
10
Anda dapat menggunakan '' untuk setlocalemenggunakan default, yang diharapkan akan sesuai.
Mark Ransom
24
Coba ini: locale.setlocale (locale.LC_ALL, '') Ini berhasil untuk saya
Nadia Alramli
1
Meskipun pintar, saya tidak suka fungsi yang membuat pengaturan global ... Menggunakan 'blah'.format () adalah cara yang lebih baik untuk melakukannya.
Cerin
132

Untuk inefisiensi dan keterbacaan sulit dikalahkan:

>>> 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('-,','-')
Kasey Kirkham
sumber
171
Memilih metode yang paling tidak efisien dan tidak dapat dibaca untuk menjawab pertanyaan ini.
psytek
1
akan lebih baik jika ini setidaknya akan berhasil. coba nomor ini "17371830" menjadi "173.718.3.0" =)
holms
5
Periode? Itu bahkan tidak mungkin, holms. Sampah ini benar-benar mengabaikan lokal. Saya ingin tahu bagaimana Anda mendapatkan hasil itu. Contoh Anda menghasilkan '17, 371.830 'untuk saya, seperti yang diharapkan.
Kasey Kirkham
11
Untuk membuat ini fungsi saya sarankan: 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))hanya untuk menjaga tema kebingungan.
kuantum
95

Berikut adalah kode pengelompokan lokal setelah menghapus bagian yang tidak relevan dan membersihkannya sedikit:

(Berikut ini hanya berfungsi untuk bilangan bulat)

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'

Sudah ada beberapa jawaban bagus di sini. Saya hanya ingin menambahkan ini untuk referensi di masa mendatang. Dalam python 2.7 akan ada penentu format untuk pemisah ribuan. Menurut python docs berfungsi seperti ini

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

Di python3.1 Anda dapat melakukan hal yang sama seperti ini:

>>> format(1234567, ',d')
'1,234,567'
Nadia Alramli
sumber
Ya, cara yang lebih sulit terutama untuk orang-orang yang menggunakan Python lama, seperti yang dikirimkan bersama RHEL dan distro dukungan jangka panjang lainnya.
Mike DeSimone
3
bagaimana cara mengekspresikan ini dengan format string? "%, d"% 1234567 tidak berfungsi
Frederic Bazin
93

Saya terkejut bahwa tidak ada yang menyebutkan bahwa Anda dapat melakukan ini dengan f-string di Python 3.6 semudah ini:

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

... di mana bagian setelah titik dua adalah penentu format. Koma adalah karakter pemisah yang Anda inginkan, jadi f"{num:_}"gunakan garis bawah alih-alih koma.

Ini sama dengan menggunakan format(num, ",")untuk versi python 3 yang lebih lama.

Emil Stenström
sumber
Ini lebih mudah daripada jawaban dengan suara lebih tinggi, dan tidak memerlukan impor tambahan.
Z4-tier
39

Berikut ini adalah penggantian satu baris regex:

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

Hanya berfungsi untuk output inegral:

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'

Atau untuk pelampung dengan kurang dari 4 digit, ubah penentu format ke %.3f:

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

NB: Tidak berfungsi dengan benar dengan lebih dari tiga digit desimal karena akan mencoba mengelompokkan bagian desimal:

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

Bagaimana itu bekerja

Mari kita jabarkan:

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
Daniel Fortunov
sumber
1
gunakan mode verbose dan Anda dapat memiliki komentar tepat di dalam kode
Daniel Stracaboško
Tidak bisakah Anda mengganti "(?! \ D)" dengan "$"?
GL2014
28

Inilah yang saya lakukan untuk kendaraan hias. Meskipun, jujur, saya tidak yakin versi kerjanya - Saya menggunakan 2.7:

my_number = 4385893.382939491

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

Pengembalian: 4,385,893.38

Pembaruan: Saya baru-baru ini memiliki masalah dengan format ini (tidak dapat memberi tahu Anda alasan yang tepat), tetapi dapat memperbaikinya dengan menjatuhkan 0:

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

Anda juga dapat menggunakan '{:n}'.format( value )untuk representasi lokal. Saya pikir ini adalah cara paling sederhana untuk solusi lokal.

Untuk informasi lebih lanjut, cari thousandsdi Python DOC .

Untuk mata uang, Anda dapat menggunakan locale.currency, mengatur bendera grouping:

Kode

import locale

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

Keluaran

'Portuguese_Brazil.1252'
'R$ 1.234.567,89'
DiogoLR
sumber
14

Sedikit memperluas jawaban Ian Schneider:

Jika Anda ingin menggunakan pemisah ribuan kustom, solusi paling sederhana adalah:

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

Contohnya

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

Jika Anda ingin representasi Jerman seperti ini, itu akan sedikit lebih rumit:

('{:,.2f}'.format(123456789.012345)
          .replace(',', ' ')  # 'save' the thousands separators 
          .replace('.', ',')  # dot to comma
          .replace(' ', '.')) # thousand separators to dot
Martin Thoma
sumber
Sedikit lebih pendek:'{:_.2f}'.format(12345.6789).replace('.', ',').replace('_', '.')
Tom Pohl
12

Saya yakin pasti ada fungsi pustaka standar untuk ini, tetapi menyenangkan untuk mencoba menulisnya sendiri menggunakan rekursi jadi inilah yang saya buat:

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)

Karena itu, jika orang lain menemukan cara standar untuk melakukannya, Anda harus menggunakannya.

Mark Byers
sumber
Sayangnya tidak berfungsi dalam semua kasus. intToStringWithCommas (1000.1) -> '1.0001.000'
Nadia Alramli
Dia secara khusus mengatakan bilangan bulat dan harus sesederhana mungkin, jadi saya memutuskan untuk tidak menangani tipe data selain bilangan bulat. Saya juga membuatnya secara eksplisit dalam nama fungsi _int_ToStringWithCommas. Sekarang saya juga menambahkan kenaikan gaji untuk membuatnya lebih jelas.
Mark Byers
8

Dari komentar hingga resep aktivasi 498181 saya ulang ini:

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

Ini menggunakan fitur ekspresi reguler: lookahead yaitu (?=\d)untuk memastikan hanya grup dari tiga digit yang memiliki digit 'setelah' mereka mendapatkan koma. Saya katakan 'setelah' karena string terbalik pada saat ini.

[::-1] hanya membalikkan sebuah string.

Tom Viner
sumber
8

Jawaban yang diterima baik-baik saja, tetapi sebenarnya saya lebih suka format(number,','). Lebih mudah bagi saya untuk menafsirkan dan mengingat.

https://docs.python.org/3/library/functions.html#format

Magenta Nova
sumber
Berfungsi sempurna, juga menghindari menampilkan terlalu banyak angka desimal untuk mengapung.
Rexcirus
7

Python 3

-

Integer (tanpa desimal):

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

-

Mengapung (dengan desimal):

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

di mana angka sebelumnya fmenentukan jumlah tempat desimal.

-

Bonus

Fungsi starter cepat dan kotor untuk sistem penomoran lakh India / crores (12,34,567):

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

Adam Starrh
sumber
5

dari Python versi 2.6 Anda bisa melakukan ini:

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

Untuk versi Python <2.6 dan hanya untuk informasi Anda, berikut adalah 2 solusi manual, mereka berubah menjadi mengambang tetapi angka negatif berfungsi dengan benar:

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)

beberapa hal yang perlu diperhatikan di sini:

  • baris ini: string = '% d'% number mengubah angka menjadi string dengan indah, mendukung angka negatif dan menjatuhkan pecahan dari float, menjadikannya int;
  • indeks slice ini [:: - 3] mengembalikan setiap item ketiga mulai dari akhir, jadi saya menggunakan slice lain [1:] untuk menghapus item terakhir karena saya tidak perlu koma setelah nomor terakhir;
  • syarat ini jika l [indeks]! = '-' digunakan untuk mendukung angka negatif, jangan masukkan koma setelah tanda minus.

Dan versi yang lebih 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)
bahtera
sumber
2

Saya seorang pemula Python, tetapi seorang programmer yang berpengalaman. Saya memiliki Python 3.5, jadi saya hanya bisa menggunakan koma, tetapi ini tetap merupakan latihan pemrograman yang menarik. Pertimbangkan kasus bilangan bulat yang tidak ditandatangani. Program Python yang paling mudah dibaca untuk menambahkan ribuan pemisah tampaknya adalah:

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)

Dimungkinkan juga untuk menggunakan pemahaman daftar:

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)

Ini lebih pendek, dan bisa menjadi liner satu, tetapi Anda harus melakukan beberapa senam mental untuk memahami mengapa itu bekerja. Dalam kedua kasus tersebut kita mendapatkan:

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

Versi pertama adalah pilihan yang lebih masuk akal, jika Anda ingin program dipahami.

Geoff Fergusson
sumber
1

Ini salah satu yang berfungsi untuk pelampung juga:

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

Contoh Penggunaan:

>>> float2comma(10000.1111)
'10,000.111,1'
>>> float2comma(656565.122)
'656,565.122'
>>> float2comma(-656565.122)
'-656,565.122'
Edward van Kuik
sumber
1
float2comma(12031023.1323)pengembalian: '12, 031.023.132,3 '
demux
1

Satu liner untuk Python 2.5+ dan Python 3 (hanya int positif):

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

Solusi universal

Saya telah menemukan beberapa masalah dengan pemisah titik di jawaban terpilih sebelumnya. Saya telah merancang solusi universal di mana Anda dapat menggunakan apa pun yang Anda inginkan sebagai pemisah seribu tanpa mengubah lokal . Saya tahu itu bukan solusi yang paling elegan, tetapi menyelesaikan pekerjaan. Jangan ragu untuk memperbaikinya!

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
Manrique
sumber
0

Ini menghasilkan uang bersama dengan koma

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)
Bob F
sumber
0

Saya memiliki versi python 2 dan python 3 dari kode ini. Saya tahu bahwa pertanyaannya adalah python 2 tetapi sekarang (8 tahun kemudian lol) orang mungkin akan menggunakan python 3.

Python 3 Code:

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))        


Kode Python 2: (Edit. Kode python 2 tidak berfungsi. Saya berpikir bahwa sintaksnya berbeda).

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) 
Dinosaur212
sumber
0

Saya menggunakan python 2.5 jadi saya tidak memiliki akses ke pemformatan bawaan.

Saya melihat kode Django intcomma (intcomma_recurs dalam kode di bawah) dan menyadari itu tidak efisien, karena itu rekursif dan juga menyusun regex pada setiap proses bukanlah hal yang baik juga. Ini tidak perlu menjadi 'masalah' karena Django tidak benar-benar fokus pada kinerja tingkat rendah semacam ini. Juga, saya mengharapkan faktor 10 perbedaan dalam kinerja, tetapi hanya 3 kali lebih lambat.

Karena penasaran, saya menerapkan beberapa versi intcomma untuk melihat apa keunggulan kinerja saat menggunakan regex. Data pengujian saya menyimpulkan sedikit keuntungan untuk tugas ini, tetapi tidak mengejutkan sama sekali.

Saya juga senang melihat apa yang saya duga: menggunakan pendekatan reverse xrange tidak perlu dalam kasus no-regex, tetapi itu membuat kode terlihat sedikit lebih baik dengan biaya kinerja ~ 10%.

Juga, saya menganggap apa yang Anda lewati adalah string dan terlihat agak seperti angka. Hasil tidak ditentukan sebaliknya.

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

Dan inilah hasil tesnya:

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
paritas3
sumber
Saya pikir solusi satu-regex Daniel Fortunov akan menjadi # 1 dan mengalahkan semua algoritma karena regex sangat disempurnakan / dioptimalkan dan dikodekan dalam C, tetapi tidak .. Saya kira pola dan lookahead terlalu mahal. itu jatuh pada sekitar dua kali lipat waktu intcomma di atas, bahkan dengan mengkompilasi regex.
parity3
0

ini dimasukkan ke dalam python per PEP -> https://www.python.org/dev/peps/pep-0378/

cukup gunakan format (1000, ', d') untuk menunjukkan integer dengan ribuan pemisah

ada lebih banyak format yang dijelaskan dalam PEP, miliki

Raveen Beemsingh
sumber
-1

Berikut ini varian lain yang menggunakan fungsi generator yang berfungsi untuk bilangan bulat:

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)]))

Dan inilah tesnya:

>>> 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
pengguna650654
sumber
-1

Hanya subkelas long(atau float, atau apa pun). Ini sangat praktis, karena dengan cara ini Anda masih dapat menggunakan angka-angka Anda dalam operasi matematika (dan karena itu kode yang ada), tetapi semuanya akan dicetak dengan baik di terminal Anda.

>>> 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
twneale
sumber
8
Saya suka ide subclass, tetapi apakah __repr__()metode yang tepat untuk menimpanya? Saya akan menyarankan mengesampingkan __str__()dan meninggalkan __repr__()sendirian, karena int(repr(number(928374)))harus bekerja, tetapi int()akan tersedak koma.
steveha
@steveha memiliki poin yang bagus, tetapi pembenaran seharusnya number(repr(number(928374)))tidak bekerja, tidak int(repr(number(928374))). Semua sama, untuk membuat pendekatan ini bekerja secara langsung dengan print, seperti yang diminta OP, __str__()metode harus menjadi yang ditimpa daripada __repr__(). Apapun, tampaknya ada bug dalam logika penyisipan koma inti.
martineau
-1

Italia:

>>> import locale
>>> locale.setlocale(locale.LC_ALL,"")
'Italian_Italy.1252'
>>> f"{1000:n}"
'1.000'
Giovanni G. PY
sumber
-8

Untuk mengapung:

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

Untuk int:

int(filter(lambda x: x!=',', '1,234'))
# returns 1234
Jennifer
sumber
5
Itu menghilangkan koma. Meskipun praktis, OP meminta cara untuk menambahkannya . Selain itu, sesuatu seperti float('1,234.52'.translate(None, ','))mungkin lebih mudah dan mungkin lebih cepat.
Dijeda sampai pemberitahuan lebih lanjut.