ChatGPT解决这个技术问题 Extra ChatGPT

如何使用逗号作为千位分隔符打印数字

如何打印带有逗号作为千位分隔符的整数?

1234567   ⟶   1,234,567

在句点和逗号之间决定不需要特定于语言环境。


M
Mateen Ulhaq

语言环境不知道

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

区域感知

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

参考

Format Specification Mini-Language

',' 选项表示使用逗号作为千位分隔符。对于区域设置感知分隔符,请改用“n”整数表示类型。


请注意,这在美国和其他少数地方以外是不正确的,在这种情况下,选择的 locale.format() 是正确的答案。
关键字参数形式:{val:,}.format(val=val)
太谢谢了。对于金额,小数点后 2 位 - "{:,.2f}".format(value)
在 python 3.6 及更高版本中,f-strings 更加方便。例如f"{2 ** 64 - 1:,}"
区域设置感知版本如何工作? (使用“n”整数表示类型)
M
Mike DeSimone

我得到了这个工作:

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

当然,您不需要国际化支持,但它清晰、简洁并使用内置库。

PS 那 "%d" 是通常的 %-style 格式化程序。您只能拥有一个格式化程序,但它可以是您在字段宽度和精度设置方面所需的任何内容。

PPS 如果您无法让 locale 工作,我建议您修改一下 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)

递归对否定情况很有用,但每个逗号一个递归对我来说似乎有点过分。


我试过你的代码,不幸的是,我得到了这个:“locale.Error:不支持的语言环境设置”。 :-s
Mark:如果你在 Linux 上,你可能想看看 /etc/locale.gen 中有什么,或者你的 glibc 使用什么来构建它的语言环境。您可能还想尝试 ""en"、"en_US.utf8"、"en_US.UTF-8"、'en_UK" (sp?) 等。 mikez:需要一本书:“PEP 博士:或者我如何学会停止担心并热爱 docs.python.org。”我放弃了记住 Python 1.5.6 前后的所有库。至于locale,我尽量少用。
您可以使用 setlocale 的 '' 来使用默认值,希望这是合适的。
试试这个: locale.setlocale(locale.LC_ALL, '') 它对我有用
虽然很聪明,但我不喜欢进行全局设置的函数......使用 'blah'.format() 是更好的方法。
E
Emil Stenström

我很惊讶没有人提到你可以在 Python 3.6+ 中使用 f-strings 做到这一点,就像这样简单:

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

...冒号后面的部分是格式说明符。逗号是您想要的分隔符,因此 f"{num:_}" 使用下划线而不是逗号。此方法只能使用“,”和“_”。

这相当于对旧版本的 python 3 使用 format(num, ",")

当您第一次看到它时,这可能看起来很神奇,但事实并非如此。它只是语言的一部分,并且通常需要足够的东西来提供可用的快捷方式。要了解更多信息,请查看 the group subcomponent


这比任何投票率较高的答案都容易,并且不需要额外的导入。
@NoName这个答案还提到了如何使用适用于所有版本的python3的str.format()来做到这一点,几乎一样简单并且不使用f-strings
这是最好和最简单的答案。
有时我会向下滚动 SO 问题。当我找到这样的宝石时,我知道这是值得的。
@Hills:只能使用 , 和 _ 这种方法(上面更新)。详情如下:realpython.com/python-formatted-output/#the-group-subcomponent
K
Kasey Kirkham

对于低效率和不可读性,它很难被击败:

>>> 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('-,','-')

投票支持最低效且难以理解的方法来回答这个问题。
如果这至少可行的话会很好。试试这个数字“17371830”它变成“173.718.3.0”=)
时期?那是不可能的,霍姆斯。这块垃圾完全忽略了语言环境。我想知道你是怎么得到这个结果的。正如预期的那样,您的示例为我生成了“17,371,830”。
为了使它成为一个功能,我建议: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)) 只是为了保留混淆主题。
M
Martijn Pieters

这是删除不相关部分并稍微清理一下之后的语言环境分组代码:

(以下仅适用于整数)

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'

这里已经有一些很好的答案。我只是想添加这个以供将来参考。在 python 2.7 中,将有一个千位分隔符的格式说明符。根据 python docs,它的工作原理是这样的

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

在 python3.1 中,你可以这样做:

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

是的,更难的方法主要适用于使用较旧 Python 的人,例如那些附带 RHEL 和其他长期支持发行版的人。
如何用格式字符串表达这一点? "%,d" % 1234567 不起作用
对我来说,这个答案提供了完美的{:15,d}'.format(len(SortedList))
令人惊讶的是,format(1234567, ',d') 也适用于 python 2.7
肯定 format(1234567, ',') 是最简单的答案。
D
Daniel Fortunov

这是一个单行正则表达式替换:

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

仅适用于积分输出:

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'

或者对于少于 4 位的浮点数,将格式说明符更改为 %.3f

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

注意:不能正确使用超过三个小数位,因为它会尝试对小数部分进行分组:

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

这个怎么运作

让我们分解一下:

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

使用详细模式,您可以在代码中添加注释
你不能用 "$" 替换 "(?!\d)" 吗?
e
elPastor

这就是我为花车所做的。虽然,老实说,我不确定它适用于哪些版本 - 我使用的是 2.7:

my_number = 4385893.382939491

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

回报:4,385,893.38

更新:我最近遇到了这种格式的问题(无法告诉你确切的原因),但能够通过删除 0 来解决它:

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

D
Diogo

您还可以使用 '{:n}'.format( value ) 表示语言环境。我认为这是语言环境解决方案的最简单方法。

有关详细信息,请在 Python DOC 中搜索 thousands

对于货币,您可以使用 locale.currency,设置标志 grouping

代码

import locale

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

输出

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

M
Martin Thoma

稍微扩展 Ian Schneider 的答案:

如果要使用自定义千位分隔符,最简单的解决方案是:

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

例子

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

如果你想要这样的德语表示,它会变得有点复杂:

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

略短:'{:_.2f}'.format(12345.6789).replace('.', ',').replace('_', '.')
M
Mark Byers

我确信必须有一个标准的库函数,但是尝试使用递归自己编写它很有趣,所以这就是我想出的:

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)

话虽如此,如果其他人确实找到了一种标准方法,那么您应该改用它。


不幸的是,并非在所有情况下都有效。 intToStringWithCommas(1000.1) -> '1.0001,000'
他特别提到了整数,它应该尽可能简单,所以我决定不处理整数以外的数据类型。我还在函数名 _int_ToStringWithCommas 中明确说明了这一点。现在我还添加了加注以使其更清楚。
T
Thavas Antonio

以下是一些格式化的方法(与浮点数和整数兼容)

num = 2437.68

# Way 1: String Formatting

'{:,}'.format(num)
>>> '2,437.68'


# Way 2: F-Strings

f'{num:,}'
>>> '2,437.68'


# Way 3: Built-in Format Function

format(num, ',')
>>> '2,437.68'

T
Tom Viner

comments 到 activestate 配方 498181 我修改了这个:

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

它使用正则表达式功能:lookahead(?=\d) 来确保只有在它们之后有一个数字的三位数组得到逗号。我说“之后”是因为此时字符串是反向的。

[::-1] 只是反转一个字符串。


M
Magenta Nova

接受的答案很好,但我实际上更喜欢 format(number,',')。我更容易理解和记住。

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


完美运行,同时避免显示过多的浮点数。
A
Adam Starrh

蟒蛇 3

--

整数(无小数):

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

--

浮点数(带小数):

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

其中 f 之前的数字指定小数位数。

--

奖金

印度十万/千万卢比编号系统 (12,34,567) 的快速入门功能:

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


a
arka

从 Python 2.6 版开始,您可以这样做:

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

对于 Python 版本 < 2.6 并且仅供参考,这里有 2 个手动解决方案,它们将浮点数转换为整数,但负数可以正常工作:

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)

这里有几点需要注意:

这一行: string = '%d' % number 漂亮地将数字转换为字符串,它支持负数,并且从浮点数中删除分数,使它们成为整数;

此切片索引 [::-3] 从末尾开始返回每三个项目,因此我使用另一个切片 [1:] 删除最后一个项目,因为我不需要在最后一个数字后使用逗号;

这个条件如果 l[index] != '-' 用于支持负数,请不要在减号后插入逗号。

还有一个更硬核的版本:

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)

T
Tunaki

我是一名 Python 初学者,但也是一名经验丰富的程序员。我有 Python 3.5,所以我可以只使用逗号,但这仍然是一个有趣的编程练习。考虑无符号整数的情况。用于添加千位分隔符的最易读的 Python 程序似乎是:

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)

也可以使用列表推导:

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)

这更短,并且可能是单线,但你必须做一些心理体操才能理解它为什么有效。在这两种情况下,我们得到:

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

如果您希望程序被理解,第一个版本是更明智的选择。


M
Manrique

通用解决方案

我在之前投票最多的答案中发现了点分隔符的一些问题。我设计了一个通用解决方案,您可以在其中使用任何您想要的千位分隔符,而无需修改语言环境。我知道这不是最优雅的解决方案,但它可以完成工作。随意改进它!

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

S
Seyed Mahdi Kermani

在浮点数中一起使用分隔符和小数:(在本例中,两位小数)

large_number = 4545454.26262666
print(f"Formatted: {large_number:,.2f}")

结果:格式化:4,545,454.26


E
Edward van Kuik

这也适用于花车:

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

使用示例:

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

float2comma(12031023.1323) 返回:'12,031,023.132,3'
C
Collin Anderson

适用于 Python 2.5+ 和 Python 3 的一个内衬(仅限正整数):

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

i
idjaw

我使用的是 python 2.5,所以我无法访问内置格式。

我查看了 Django 代码 intcomma(下面代码中的 intcomma_recurs)并意识到它效率低下,因为它是递归的,而且每次运行时编译正则表达式也不是一件好事。这不是一个“问题”,因为 django 并没有真正专注于这种低级性能。此外,我预计性能会相差 10 倍,但它只慢了 3 倍。

出于好奇,我实现了几个版本的 intcomma 以了解使用正则表达式时的性能优势。我的测试数据得出的结论是,这项任务略有优势,但令人惊讶的是根本没有优势。

我也很高兴看到我所怀疑的:在没有正则表达式的情况下,不需要使用反向 xrange 方法,但它确实使代码看起来稍微好一些,但代价是大约 10% 的性能。

另外,我假设你传入的是一个字符串,看起来有点像一个数字。结果未确定。

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

以下是测试结果:

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

我认为 Daniel Fortunov 的单一正则表达式解决方案将是 #1 并击败所有算法,因为正则表达式是如此精炼/优化并用 C 编码,但不是......我猜模式和前瞻太昂贵了。即使预编译了正则表达式,它也大约是上述 intcomma 时间的两倍。
n
navule

python 中的 babel 模块具有根据提供的语言环境应用逗号的功能。

要安装 babel,请运行以下命令。

pip install babel

用法

format_currency(1234567.89, 'USD', locale='en_US')
# Output: $1,234,567.89
format_currency(1234567.89, 'USD', locale='es_CO')
# Output: US$ 1.234.567,89 (raw output US$\xa01.234.567,89)
format_currency(1234567.89, 'INR', locale='en_IN')
# Output: ₹12,34,567.89

B
Bob F

这和逗号一起赚钱

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)

我知道这是一个古老的答案,但如果他们使用浮点数进行货币计算,任何人都会受到伤害。浮点数不精确!查找 IEEE 754,远离地狱之路。
@ingyhere 具有讽刺意味的是,IEEE 754 双精度可以容纳高达 2**53 的任何整数,而不会损失任何精度。 Javascript 甚至不需要使用整数类型。
D
Dinosaur212

我有这个代码的 python 2 和 python 3 版本。我知道这个问题是针对 python 2 提出的,但现在(8 年后大声笑)人们可能会使用 python 3。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))        

Python 2 代码:(编辑。python 2 代码不起作用。我认为语法不同)。

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) 

R
Raveen Beemsingh

这是根据 PEP 烘焙到 python 中的-> https://www.python.org/dev/peps/pep-0378/

只需使用 format(1000, ',d') 显示带有千位分隔符的整数

PEP 中描述了更多格式,请参阅


u
user650654

这是另一个使用适用于整数的生成器函数的变体:

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

这是一个测试:

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

P
PythonProgrammi

意大利:

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

i
idjaw

只是子类 long(或 float,或其他)。这是非常实用的,因为这样您仍然可以在数学运算(以及现有代码)中使用您的数字,但它们都会在您的终端中很好地打印出来。

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

我喜欢子类的想法,但是 __repr__() 是正确的覆盖方法吗?我建议覆盖 __str__() 并单独留下 __repr__(),因为 int(repr(number(928374))) 应该可以工作,但 int() 会因逗号而窒息。
@steveha 有一个很好的观点,但理由应该是 number(repr(number(928374))) 不起作用,而不是 int(repr(number(928374)))。尽管如此,为了使这种方法直接与 print 一起工作,按照 OP 的要求,__str__() 方法应该是被覆盖的方法而不是 __repr__()。无论如何,核心逗号插入逻辑中似乎存在错误。
D
Dennis Williamson

对于花车:

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

对于整数:

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

删除逗号。虽然方便,但 OP 要求提供一种 add 它们的方法。此外,像 float('1,234.52'.translate(None, ',')) 这样的东西可能更直接,也可能更快。