Làm thế nào để in số bằng dấu phẩy như hàng ngàn dấu phân cách?


754

Tôi đang cố gắng in một số nguyên trong Python 2.6.1 với dấu phẩy là hàng nghìn dấu phân cách. Ví dụ, tôi muốn hiển thị số 1234567như 1,234,567. Tôi sẽ đi đâu để tới đó? Tôi đã thấy nhiều ví dụ trên Google, nhưng tôi đang tìm kiếm cách thực tế đơn giản nhất.

Không cần phải là địa phương cụ thể để quyết định giữa các dấu chấm và dấu phẩy. Tôi muốn một cái gì đó đơn giản như hợp lý có thể.

Câu trả lời:


1739

Địa phương không biết

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

Nhận thức địa phương

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

Tài liệu tham khảo

Mỗi định dạng Đặc điểm kỹ thuật Mini-Language ,

Các ','tùy chọn báo hiệu việc sử dụng dấu phẩy để phân cách hàng ngàn. Đối với dấu phân cách nhận biết miền địa phương, hãy sử dụng 'n'loại trình bày số nguyên thay thế.


25
Lưu ý rằng điều này sẽ không chính xác ngoài Hoa Kỳ và một vài nơi khác, trong trường hợp đó, locale.format () được chọn là câu trả lời đúng.
Gringo Suave

11
Mẫu đối số từ khóa:{val:,}.format(val=val)
CivilFan

11
Cảm ơn rất nhiều. Đối với số tiền, với 2 chữ số thập phân - "{:,. 2f}". Định dạng (giá trị)
dlink

3
đối với Bồ Đào Nha, nơi chúng tôi sử dụng điểm (.) làm dấu phân cách: {:,} ". format (value) .replace (',', '.')

13
Trong python 3.6 trở lên, chuỗi f thêm tiện lợi hơn nữa. Ví dụ:f"{2 ** 64 - 1:,}"
CJ Gaconnet

285

Tôi đã làm việc này:

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

Chắc chắn, bạn không cần hỗ trợ quốc tế hóa, nhưng rõ ràng, súc tích và sử dụng thư viện tích hợp.

PS "% d" là định dạng% kiểu thông thường. Bạn có thể chỉ có một trình định dạng, nhưng nó có thể là bất cứ thứ gì bạn cần về độ rộng trường và cài đặt chính xác.

PPS Nếu bạn không thể localelàm việc, tôi muốn đề xuất một phiên bản sửa đổi của câu trả lời của 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)

Đệ quy là hữu ích cho trường hợp tiêu cực, nhưng một đệ quy trên mỗi dấu phẩy có vẻ hơi quá đối với tôi.


14
Tôi đã thử mã của bạn và thật không may, tôi nhận được điều này: "locale.Error: cài đặt ngôn ngữ không được hỗ trợ". : -s
Mark Byers

11
Đánh dấu: Nếu bạn đang sử dụng Linux, bạn có thể muốn xem những gì trong /etc/locale.gen hoặc bất cứ thứ gì mà glibc của bạn đang sử dụng để xây dựng các địa điểm của nó. Bạn cũng có thể muốn thử "" en "," en_US.utf8 "," en_US.UTF-8 ", 'en_UK" (sp?), V.v. mikez: Cần phải có một cuốn sách: "Dr. PEP: Hoặc Làm thế nào tôi học được cách ngừng lo lắng và yêu docs.python.org. " Tôi đã từ bỏ việc ghi nhớ tất cả các thư viện xung quanh Python 1.5.6. Đối với locale, tôi sử dụng ít nhất có thể.
Mike DeSimone

10
Bạn có thể sử dụng '' setlocaleđể sử dụng mặc định, hy vọng sẽ phù hợp.
Đánh dấu tiền chuộc

24
Hãy thử điều này: locale.setlocale (locale.LC_ALL, '') Nó hoạt động với tôi
Nadia Alramli

1
Mặc dù thông minh, tôi không thích các chức năng tạo cài đặt toàn cầu ... Sử dụng 'blah'.format () là cách tốt hơn để sử dụng.
Cerin

132

Đối với sự không hiệu quả và không thể đọc được, thật khó để đánh bại:

>>> 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
Bỏ phiếu cho hầu hết các phương pháp không hiệu quả và không thể đọc được để trả lời câu hỏi này.
psytek

1
sẽ tốt nếu điều này ít nhất sẽ làm việc thử con số này "17371830" nó trở nên "173.718.3.0" =)
Holms

5
Chu kỳ? Điều đó thậm chí không thể, holms. Mảnh rác này hoàn toàn bỏ qua miền địa phương. Tôi tự hỏi làm thế nào bạn có kết quả đó. Ví dụ của bạn tạo ra '17, 371.830 'cho tôi, như mong đợi.
Kasey Kirkham

11
Để làm cho điều này một chức năng tôi sẽ đề nghị: 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))chỉ để giữ cho chủ đề obfuscation.
lượng tử

95

Đây là mã nhóm địa phương sau khi loại bỏ các phần không liên quan và làm sạch nó một chút:

(Phần sau chỉ hoạt động cho số nguyên)

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'

Đã có một số câu trả lời tốt ở đây. Tôi chỉ muốn thêm điều này để tham khảo trong tương lai. Trong python 2.7 sẽ có một bộ định dạng định dạng cho hàng nghìn dấu phân cách. Theo tài liệu python nó hoạt động như thế này

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

Trong python3.1, bạn có thể làm điều tương tự như thế này:

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

Vâng, những cách khó hơn chủ yếu dành cho những người trên Pythons cũ, chẳng hạn như những người được vận chuyển với RHEL và các bản phân phối hỗ trợ dài hạn khác.
Mike DeSimone

3
Làm thế nào để thể hiện điều này với chuỗi định dạng? "%, d"% 1234567 không hoạt động
Frederic Bazin

93

Tôi ngạc nhiên khi không ai đề cập rằng bạn có thể làm điều này với chuỗi f trong Python 3.6 dễ dàng như thế này:

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

... Trong đó phần sau dấu hai chấm là định dạng định dạng. Dấu phẩy là ký tự phân cách bạn muốn, vì vậy f"{num:_}"sử dụng dấu gạch dưới thay vì dấu phẩy.

Điều này tương đương với việc sử dụng format(num, ",")cho các phiên bản cũ hơn của python 3.


Điều này dễ hơn bất kỳ câu trả lời nào được bình chọn cao hơn và không yêu cầu nhập thêm.
Z4-tier

39

Đây là một thay thế regex một dòng:

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

Chỉ hoạt động cho đầu ra 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'

Hoặc đối với số float có ít hơn 4 chữ số, hãy thay đổi định dạng định dạng thành %.3f:

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

Lưu ý: Không hoạt động chính xác với hơn ba chữ số thập phân vì nó sẽ cố gắng nhóm phần thập phân:

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

Làm thế nào nó hoạt động

Hãy phá vỡ nó:

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
sử dụng chế độ dài dòng và bạn có thể có ý kiến ​​ngay bên trong mã
Daniel Stracaboško

Bạn không thể thay thế "(?! \ D)" bằng "$"?
GL2014

28

Đây là những gì tôi làm cho phao. Mặc dù, thành thật mà nói, tôi không chắc nó hoạt động cho phiên bản nào - Tôi đang sử dụng 2.7:

my_number = 4385893.382939491

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

Trả về: 4.385.893,38

Cập nhật: Gần đây tôi gặp sự cố với định dạng này (không thể cho bạn biết lý do chính xác), nhưng đã có thể khắc phục bằng cách bỏ 0:

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

19

Bạn cũng có thể dùng '{:n}'.format( value ) cho một đại diện miền địa phương. Tôi nghĩ rằng đây là cách đơn giản nhất cho một giải pháp địa phương.

Để biết thêm thông tin, tìm kiếm thousandstrong Python DOC .

Đối với tiền tệ, bạn có thể sử dụng locale.currency, đặt cờgrouping :

import locale

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

Đầu ra

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

13

Hơi mở rộng câu trả lời của Ian Schneider:

Nếu bạn muốn sử dụng một dấu tách hàng nghìn tùy chỉnh, giải pháp đơn giản nhất là:

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

Ví dụ

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

Nếu bạn muốn đại diện của Đức như thế này, nó sẽ phức tạp hơn một chút:

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

Hơi ngắn hơn một chút:'{:_.2f}'.format(12345.6789).replace('.', ',').replace('_', '.')
Tom Pohl

12

Tôi chắc chắn phải có một chức năng thư viện tiêu chuẩn cho việc này, nhưng thật vui khi cố gắng tự viết nó bằng cách sử dụng đệ quy vì vậy đây là những gì tôi nghĩ ra:

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)

Đã nói rằng, nếu người khác tìm thấy một cách tiêu chuẩn để làm điều đó, bạn nên sử dụng nó để thay thế.


Thật không may, không hoạt động trong mọi trường hợp. intToStringWithCommas (1000.1) -> '1.0001.000'
Nadia Alramli

Ông đặc biệt nói số nguyên và nó phải đơn giản nhất có thể, vì vậy tôi quyết định không xử lý các kiểu dữ liệu khác với số nguyên. Tôi cũng đã làm cho nó rõ ràng trong tên hàm _int_ToStringWithCommas. Bây giờ tôi cũng đã thêm một mức tăng để làm cho nó rõ ràng hơn.
Mark Byers

8

Từ các ý kiến để kích hoạt công thức 498181 tôi đã làm lại điều này:

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

Nó sử dụng tính năng biểu thức chính quy: lookahead tức là(?=\d) để đảm bảo chỉ các nhóm ba chữ số có một chữ số 'sau' chúng có dấu phẩy. Tôi nói 'sau' bởi vì chuỗi này đảo ngược tại thời điểm này.

[::-1] chỉ cần đảo ngược một chuỗi.



7

Con trăn 3

-

Số nguyên (không có số thập phân):

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

-

Phao (có số thập phân):

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

trong đó số trước fchỉ định số vị trí thập phân.

-

Tặng kem

Chức năng khởi động nhanh và bẩn cho hệ thống đánh số lakhs / crores Ấn Độ (12,34,567):

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


5

từ Python phiên bản 2.6 bạn có thể làm điều này:

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

Đối với các phiên bản Python <2.6 và chỉ dành cho thông tin của bạn, đây là 2 giải pháp thủ công, chúng biến số float thành số nguyên nhưng số âm hoạt động chính xác:

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)

Một vài điều cần chú ý ở đây:

  • dòng này: string = '% d'% number đẹp mắt chuyển đổi một số thành một chuỗi, nó hỗ trợ phủ định và nó giảm phân số từ số float, biến chúng thành ints;
  • chỉ mục lát này [:: - 3] trả về mỗi mục thứ ba bắt đầu từ cuối, vì vậy tôi đã sử dụng một lát khác [1:] để xóa mục cuối cùng vì tôi không cần dấu phẩy sau số cuối cùng;
  • điều kiện này nếu l [index]! = '-' đang được sử dụng để hỗ trợ các số âm, không chèn dấu phẩy sau dấu trừ.

Và một phiên bản khó hơn:

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

Tôi là người mới bắt đầu Python, nhưng là một lập trình viên giàu kinh nghiệm. Tôi có Python 3.5, vì vậy tôi chỉ có thể sử dụng dấu phẩy, nhưng dù sao đây cũng là một bài tập lập trình thú vị. Hãy xem xét trường hợp của một số nguyên không dấu. Chương trình Python dễ đọc nhất để thêm hàng ngàn dấu phân tách dường như là:

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)

Cũng có thể sử dụng một sự hiểu biết danh sách:

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ái này ngắn hơn, và có thể là một lớp lót, nhưng bạn sẽ phải tập thể dục tinh thần để hiểu tại sao nó hoạt động. Trong cả hai trường hợp, chúng tôi nhận được:

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

Phiên bản đầu tiên là sự lựa chọn hợp lý hơn, nếu bạn muốn chương trình được hiểu.


1

Đây là một trong những hoạt động cho phao quá:

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

Ví dụ sử dụng:

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

1
float2comma(12031023.1323)trả về: '12, 031,023.132,3 '
demux

1

Một lớp lót cho Python 2.5+ và Python 3 (chỉ int int):

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

1

Giải pháp phổ quát

Tôi đã tìm thấy một số vấn đề với dấu phân cách dấu chấm trong các câu trả lời được bình chọn hàng đầu trước đó. Tôi đã thiết kế một giải pháp phổ quát, nơi bạn có thể sử dụng bất cứ thứ gì bạn muốn như một dải phân cách mà không sửa đổi miền địa phương . Tôi biết đó không phải là giải pháp tao nhã nhất, nhưng nó hoàn thành công việc. Hãy cải thiện nó!

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

Đây là tiền cùng với dấu phẩy

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

Tôi có một phiên bản python 2 và python 3 của mã này. Tôi biết rằng câu hỏi đã được hỏi về python 2 nhưng bây giờ (8 năm sau lol) mọi người có thể sẽ sử dụng python 3.

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


Mã Python 2: (Chỉnh sửa. Mã python 2 không hoạt động. Tôi nghĩ rằng cú pháp là khác nhau).

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

Tôi đang sử dụng python 2.5 vì vậy tôi không có quyền truy cập vào định dạng tích hợp.

Tôi đã xem mã Django intcomma (intcomma_recurs trong mã bên dưới) và nhận ra nó không hiệu quả, bởi vì nó đệ quy và cũng biên dịch regex trên mỗi lần chạy cũng không phải là một điều tốt. Đây không phải là một "vấn đề" vì django không thực sự tập trung vào loại hiệu suất cấp thấp này. Ngoài ra, tôi đã mong đợi một yếu tố 10 hiệu suất khác nhau, nhưng nó chỉ chậm hơn 3 lần.

Vì tò mò tôi đã triển khai một vài phiên bản của intcomma để xem những lợi thế về hiệu suất khi sử dụng regex. Dữ liệu thử nghiệm của tôi kết luận một lợi thế nhỏ cho nhiệm vụ này, nhưng đáng ngạc nhiên là không có gì nhiều.

Tôi cũng hài lòng khi thấy những gì tôi nghi ngờ: sử dụng phương pháp xrange ngược là không cần thiết trong trường hợp không có regex, nhưng nó làm cho mã trông tốt hơn một chút với chi phí hiệu năng ~ 10%.

Ngoài ra, tôi giả sử những gì bạn truyền vào là một chuỗi và trông giống như một số. Kết quả không xác định khác.

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

Và đây là kết quả kiểm tra:

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

Tôi nghĩ rằng giải pháp một regex của Daniel Fortunov sẽ là số 1 và đánh bại tất cả các thuật toán vì regex rất tinh tế / được tối ưu hóa và được mã hóa bằng C, nhưng không .. Tôi đoán rằng mô hình và giao diện là quá đắt. nó rơi vào khoảng gấp đôi thời gian của intcomma ở trên, ngay cả với việc biên dịch trước regex.
chẵn lẻ3


-1

Đây là một biến thể khác sử dụng hàm tạo hoạt động cho các số nguyên:

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

Và đây là một bài kiểm tra:

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

Chỉ cần phân lớp long(hoặc float, hoặc bất cứ điều gì). Điều này rất thực tế, bởi vì theo cách này, bạn vẫn có thể sử dụng các số của mình trong các toán học (và do đó là mã hiện có), nhưng tất cả chúng sẽ in độc đáo trong thiết bị đầu cuối của bạn.

>>> 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
Tôi thích ý tưởng lớp con, nhưng là __repr__()phương pháp chính xác để ghi đè? Tôi sẽ đề nghị ghi đè __str__()và để lại __repr__()một mình, vì int(repr(number(928374)))phải làm việc, nhưng int()sẽ bị sặc trên dấu phẩy.
steveha

@steveha có một điểm tốt, nhưng lời biện minh lẽ ra là number(repr(number(928374)))không hoạt động, không phải int(repr(number(928374))). Tất cả đều giống nhau, để làm cho phương pháp này hoạt động trực tiếp với print, như OP yêu cầu, __str__()phương thức nên là phương thức được ghi đè hơn là __repr__(). Bất kể, dường như có một lỗi trong logic chèn dấu phẩy lõi.
martineau

-1

Nước Ý:

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

-8

Đối với phao:

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

Đối với số nguyên:

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

5
Điều đó loại bỏ dấu phẩy. Trong khi tiện dụng, OP yêu cầu một cách để thêm chúng. Bên cạnh đó, một cái gì đó như float('1,234.52'.translate(None, ','))có thể đơn giản hơn và có thể nhanh hơn.
Tạm dừng cho đến khi có thông báo mới.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.