【问题标题】:如何用逗号打印数字作为千位分隔符?
【发布时间】:2010-12-21 20:06:44
【问题描述】:

我试图在 Python 2.6.1 中打印一个整数,用逗号作为千位分隔符。例如,我想将数字1234567 显示为1,234,567。我该怎么做呢?我在谷歌上看过很多例子,但我正在寻找最简单实用的方法。

在句点和逗号之间进行选择不需要特定于语言环境。我更喜欢尽可能简单的东西。

【问题讨论】:

    标签: python number-formatting


    【解决方案1】:

    语言环境不知道

    '{:,}'.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)
    • 对于葡萄牙,我们使用点 (.) 作为分隔符:{:,}".format(value).replace(',','.')
    • 在 python 3.6 及更高版本中,f-strings 更加方便。例如。 f"{2 ** 64 - 1:,}"
    【解决方案2】:

    我得到了这个工作:

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

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

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

    P.P.S.如果您无法让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,我尽量少用。
    • 您可以使用 '' for setlocale 来使用默认值,希望这样会合适。
    • 试试这个:locale.setlocale(locale.LC_ALL, '') 它对我有用
    • 虽然聪明,但我不喜欢进行全局设置的函数...使用 'blah'.format() 是更好的方法。
    【解决方案3】:

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

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

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

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

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

    【讨论】:

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

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

    >>> 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)) 只是为了保持混淆主题。
    【解决方案5】:

    这是删除不相关部分并稍微清理一下后的区域设置分组代码:

    (以下仅适用于整数)

    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, ',') 是最简单的答案。
    【解决方案6】:

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

    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
    

    【讨论】:

    • 使用详细模式,您可以在代码中直接使用 cmets
    • 你不能用“$”替换“(?!\d)”吗?
    【解决方案7】:

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

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

    回报:4,385,893.38

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

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

    【讨论】:

      【解决方案8】:

      您也可以使用'{: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'
      

      【讨论】:

        【解决方案9】:

        稍微扩展 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('_', '.')
        【解决方案10】:

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

        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 中明确说明了这一点。现在我还添加了加薪以使其更加清晰。
        【解决方案11】:

        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) 以确保只有在它们之后有一个数字的三位数组得到逗号。我说'after'是因为此时字符串是反向的。

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

        【讨论】:

          【解决方案12】:

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

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

          【讨论】:

          • 完美运行,同时避免为浮点数显示过多的十进制数字。
          【解决方案13】:

          这里有一些格式化的方法(兼容浮点数和整数)

          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'
          

          【讨论】:

            【解决方案14】:

            Python 3

            --

            整数(无小数):

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

            --

            浮点数(带小数):

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

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

            --

            奖金

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

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

            【讨论】:

              【解决方案15】:

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

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

              对于

              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 漂亮地将数字转换为字符串,它支持负数,并且从浮点数中删除分数,使其成为整数;
              • 此切片 indexes[::-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)
              

              【讨论】:

                【解决方案16】:

                我是一名 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
                

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

                【讨论】:

                  【解决方案17】:

                  通用解决方案

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

                  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
                  

                  【讨论】:

                    【解决方案18】:

                    这也适用于浮动:

                    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'
                    【解决方案19】:

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

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

                    【讨论】:

                      【解决方案20】:

                      我使用的是 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 编码,但不是......我猜模式和前瞻太昂贵了.即使预编译正则表达式,它的时间也大约是上述内逗号的两倍。
                      【解决方案21】:

                      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
                      

                      【讨论】:

                        【解决方案22】:

                        这和逗号一起赚钱

                        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,远离地狱之路。
                        【解决方案23】:

                        我有此代码的 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) 
                        

                        【讨论】:

                          【解决方案24】:

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

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

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

                          【讨论】:

                            【解决方案25】:

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

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

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

                            【讨论】:

                              【解决方案26】:

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

                              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
                              

                              【讨论】:

                                【解决方案27】:

                                只是子类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__()。无论如何,核心逗号插入逻辑中似乎存在错误。
                                【解决方案28】:

                                意大利:

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

                                【讨论】:

                                  【解决方案29】:

                                  对于花车:

                                  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, ',')) 之类的内容可能更直接,也可能更快。
                                  猜你喜欢
                                  • 2011-10-18
                                  • 2023-03-20
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  相关资源
                                  最近更新 更多