15

更新:これまでの回答は、グループ化番号を完全にサポートしていないため、特定のロケール設定に関係する OSX のプラットフォーム関連のバグのように思われることを示しています。

更新 2: Python のバグ トラッカーでイシューをオープンしました。この問題の解決策があるかどうか見てみましょう。


ドイツの番号付け規則に従って、整数と浮動小数点数をフォーマットしたいと考えています。これは、フォーマット言語とプレゼンテーション タイプを使用して可能ですnが、私のプラットフォームでは失敗します。

  • プラットフォーム: OS X 10.8.2 (Mountain Lion)
  • Python: 2.7.3 64 ビット(v2.7.3:70274d53c1dd, Apr 9 2012, 20:52:43) [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin

例:

  • 1234=>1.234
  • 1234.56=>1.234,56
  • 1000000=>1.000.000

私がこれまでに試したこと:

  1. ドイツ語ロケールの設定

    import locale
    locale.setlocale(locale.LC_ALL, 'de_DE')
    
  2. 形式指定オプション,は、英語形式のみを認識します。

    '{:,}'.format(1234)
    '1,234'
    
    '{:,}'.format(1234.56)
    '1,234.56'
    
    '{:,}'.format(1000000)
    '1,000,000'
    
  3. Python docsによると、integer と float のプレゼンテーション タイプnは、私が望むことを行うはずですが、そうではありません。

     '{:n}'.format(1234)
     '1234'
    
     '{:n}'.format(1234.56)
     '1234,56'  # at least the comma was set correctly here
    
     '{:n}'.format(1000000)
     '1000000'
    
     '{:n}'.format(12345769.56)
     '1,23458e+07'  # it's doing weird things for large floats
    
  4. @JFSebastian に触発されたいくつかの例と比較:

    for n in [1234, 1234.56, 1000000, 12345769.56]:
        print('{0:,} {0:n}'.format(n))
        fmt, val = "%d %f", (n, n)
        print(fmt % val)
        print(locale.format_string(fmt, val))
        print(locale.format_string(fmt, val, grouping=True))
        print('-'*60)
    

    これにより、私のプラットフォームでは次の誤った結果が得られます。

        1,234 1234
        1234 1234.000000
        1234 1234,000000
        1234 1234,000000
        ------------------------------------------------------------
        1,234.56 1234,56
        1234 1234.560000
        1234 1234,560000
        1234 1234,560000
        ------------------------------------------------------------
        1,000,000 1000000
        1000000 1000000.000000
        1000000 1000000,000000
        1000000 1000000,000000
        ------------------------------------------------------------
        12,345,769.56 1,23458e+07
        12345769 12345769.560000
        12345769 12345769,560000
        12345769 12345769,560000
        ------------------------------------------------------------
    

    私が得ていない正しい結果は次のようになります。

        1,234 1.234
        1234 1234.000000
        1234 1234,000000
        1.234 1.234,000000
        ------------------------------------------------------------
        1,234.56 1.234,56
        1234 1234.560000
        1234 1234,560000
        1.234 1.234,560000
        ------------------------------------------------------------
        1,000,000 1.000.000
        1000000 1000000.000000
        1000000 1000000,000000
        1.000.000 1.000.000,000000
        ------------------------------------------------------------
        12,345,769.56 1,23458e+07 
        12345769 12345769.560000
        12345769 12345769,560000
        12.345.769 12.345.769,560000
        ------------------------------------------------------------
    

フォーマット言語のみを使用した解決策はありますか? プラットフォームのロケール設定をだましてグループ化を受け入れる方法はありますか?

4

5 に答える 5

10

非常に醜いですが、技術的には質問に答えます:

PEP 378から:

'{:,}'.format(1234.56).replace(",", "X").replace(".", ",").replace("X", ".")
'1.234,56'
于 2013-01-11T21:50:36.360 に答える
6

残念ながら、 Python のlocaleモジュールの実装は、プラットフォームによってかなり異なります。これは実際には、C ライブラリ ベンダーのロケールの概念に対する軽いラッパーにすぎません。

そのため、Python 2.7.3 64 ビットを使用する Windows 7 では、これがたまたま機能します (注: Windows ではロケールの名前が異なります)。

>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'deu_deu')
'German_Germany.1252'
>>> '{0:n}'.format(1234.56)
'1.234,56'

千単位の区切り記号を使用するかどうかは、 「ローカル規則」を調べることで決定できます。

>>> locale.localeconv()['grouping'] # On Windows, 'deu_deu'.
[3, 0] # Insert separator every three digits.

>>> locale.localeconv()['grouping'] # On OS X, 'de_DE'.
[127] # No separator (locale.CHAR_MAX == 127).

>>> locale.localeconv()['grouping'] # Default C locale.
[] # Also no separator.
于 2013-01-11T22:31:44.283 に答える
5

これは、ドイツ語ロケールで使用するとうまくいきました。

>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'de_DE')
'de_DE'
>>> '{0:n}'.format(1234.56)
'1.234,56'

これは、Windows 7 の Cygwin にあります。

>>> import sys
>>> print sys.version
2.6.5 (r265:79063, Jun 12 2010, 17:07:01)
[GCC 4.3.4 20090804 (release) 1]
于 2013-01-11T22:06:43.700 に答える
1

@Lattyware から、形式言語を使用せずにドイツの番号付け規則に従ってセパレータを含めるための独自のソリューションを提供するように依頼されました。これが私が思いつくことができる最善の解決策です:

import re

def group_num(num):
    if isinstance(num, (int, float)):
        if isinstance(num, float):
            head, tail = str(num).split('.')
        elif isinstance(num, int):
            head, tail = str(num), ''
        digit_parts = re.findall(r'\d{1,3}\-?', ''.join(head[::-1]))
        num = '.'.join(part[::-1] for part in digit_parts[::-1])
        if tail:
            num = ','.join((num, tail))
        return num
    else:
        raise TypeError(num, 'is not of type int or float')

>>> group_num(1234)
'1.234'
>>> group_num(123456.7890)
'123.456,789'
>>> group_num(-1000000000.12)
'-1.000.000.000,12'

@Jon-Ericによって提供されたソリューションと比較して、パフォーマンスも非常に良好です。

%timeit group_num(1000000000.12)
10000 loops, best of 3: 20.6 us per loop

# For integers, it's faster since several steps are not necessary
%timeit group_num(100000000012)
100000 loops, best of 3: 18.2 us per loop

%timeit '{:,}'.format(1000000000.12).replace(",", "X").replace(".", ",").replace("X", ".")
100000 loops, best of 3: 2.63 us per loop

%timeit '{:,}'.format(100000000012).replace(",", "X").replace(".", ",").replace("X", ".")
100000 loops, best of 3: 2.01 us per loop

私のソリューションを最適化する方法を知っている場合は、お知らせください。

于 2013-01-12T20:35:47.797 に答える