title: How can I print any float, like 1.234e22, in a long, nicely rounded and localized format in python?
body: <p>There are a few <a href="https://stackoverflow.com/questions/13082620/how-can-i-print-a-float-with-thousands-separators">existing questions</a> about float formatting, but none answer the following question, I think.</p>
  
  <p>I'm looking for a way to print large floats in a long, nicely rounded and localized format:</p>
  
  <pre><code>&gt;&gt;&gt; print magic_format(1.234e22, locale="en_US")
  12,340,000,000,000,000,000,000
  &gt;&gt;&gt; print magic_format(1.234e22, locale="fr_FR")
  12 340 000 000 000 000 000 000
  </code></pre>
  
  <p>Unfortunately, <code>magic_format</code> does not exist.  ;-)  How can I implement it?</p>
  
  <p><strong>Details</strong></p>
  
  <p>Here are a few ways to print floats.  None of them produces the above output:</p>
  
  <pre><code>&gt;&gt;&gt; x = 1.234e22
  &gt;&gt;&gt; print str(x)
  1.234e+22
  &gt;&gt;&gt; print repr(x)
  1.234e+22
  &gt;&gt;&gt; print "%f" % x
  12339999999999998951424.000000
  &gt;&gt;&gt; print "%g" % x
  1.234e+22
  </code></pre>
  
  <p>Fail: either I get the short version, or a non-grouping non-localized non-rounded output.</p>
  
  <p>BTW, I understand that 1.234e22 cannot be stored exactly as a float, there's a necessary rounding error (that explains the odd output above).  But since <code>str</code>, <code>repr</code> and <code>"%g" % x</code> are able to properly round that to the proper value, I would like to have the same friendly rounded number, but in a long and localized form.</p>
  
  <p>Let's try localizing now...</p>
  
  <pre><code>&gt;&gt;&gt; import locale
  &gt;&gt;&gt; locale.setlocale(locale.LC_ALL, "en_US")
  'en_US'
  &gt;&gt;&gt; locale.format("%g", x, grouping = True)
  '1.234e+22'
  &gt;&gt;&gt; locale.format("%f", x, grouping = True)
  '12,339,999,999,999,998,951,424.000000'
  &gt;&gt;&gt; locale.setlocale(locale.LC_ALL, "fr_FR")
  'fr_FR'
  &gt;&gt;&gt; locale.format("%g", x, grouping = True)
  '1,234e+22'
  &gt;&gt;&gt; locale.format("%f", x, grouping = True)
  '12339999999999998951424,000000'
  </code></pre>
  
  <p>Closer, but not ok.  I still have the annoying rounding error, and the French localization sucks, it does not allow grouping at all.</p>
  
  <p>So let's use the excellent <a href="http://babel.edgewall.org/" rel="nofollow noreferrer">Babel</a> library, perhaps it can do everything I want:</p>
  
  <pre><code>&gt;&gt;&gt; from babel.numbers import format_number
  &gt;&gt;&gt; format_number(x, locale = "en_US")
  u'12,339,999,999,999,998,951,424'
  &gt;&gt;&gt; format_number(x, locale = "fr_FR")
  u'12\xa0339\xa0999\xa0999\xa0999\xa0998\xa0951\xa0424'
  </code></pre>
  
  <p>Wow, really close.  They even use non-breakable spaces for grouping in French, I love it.  It's really too bad they still have the rounding issue.</p>
  
  <p>Hey!? What if I used <a href="http://docs.python.org/2/library/decimal.html" rel="nofollow noreferrer">python Decimals</a>?</p>
  
  <pre><code>&gt;&gt;&gt; from decimal import Decimal
  &gt;&gt;&gt; Decimal(x)
  Decimal('12339999999999998951424')
  &gt;&gt;&gt; Decimal("%g" % x)
  Decimal('1.234E+22')
  &gt;&gt;&gt; "%g" % Decimal("%g" % x)
  '1.234e+22'
  &gt;&gt;&gt; "%f" % Decimal("%g" % x)
  '12339999999999998951424.000000'
  </code></pre>
  
  <p>Nope.  I can get an exact representation of the number I want with <code>Decimal("%g" % x)</code>, but whenever I try to display it, it's either short or converted to a bad float before it's printed.</p>
  
  <p>But what if I mixed Babel and Decimals?</p>
  
  <pre><code>&gt;&gt;&gt; Decimal("%g" % 1.234e22)
  Decimal('1.234E+22')
  &gt;&gt;&gt; dx = _
  &gt;&gt;&gt; format_number(dx, locale = "en_US")
  Traceback (most recent call last):
  ...
  TypeError: bad operand type for abs(): 'str'
  </code></pre>
  
  <p>Ouch.  But Babel's got a function called <code>format_decimal</code>, let's use that instead:</p>
  
  <pre><code>&gt;&gt;&gt; from babel.numbers import format_decimal
  &gt;&gt;&gt; format_decimal(dx, locale = "en_US")
  Traceback (most recent call last):
  ...
  TypeError: bad operand type for abs(): 'str'
  </code></pre>
  
  <p>Oops, <code>format_decimal</code> can't format python Decimals.  :-(</p>
  
  <p>Ok, one last idea: I could try converting to a <code>long</code>.</p>
  
  <pre><code>&gt;&gt;&gt; x = 1.234e22
  &gt;&gt;&gt; long(x)
  12339999999999998951424L
  &gt;&gt;&gt; long(Decimal(x))
  12339999999999998951424L
  &gt;&gt;&gt; long(Decimal("%g" % x))
  12340000000000000000000L
  </code></pre>
  
  <p>Yes! I've got the exact number I want to format. Let's give that to Babel:</p>
  
  <pre><code>&gt;&gt;&gt; format_number(long(Decimal("%g" % x)), locale = "en_US")
  u'12,339,999,999,999,998,951,424'
  </code></pre>
  
  <p>Oh, no...  Apparently Babel converts the <code>long</code> to a <code>float</code> before trying to format it.  I'm out of luck, and out of ideas.  :-(</p>
  
  <p>If you think that this is tough, then try answering the same question for <code>x = 1.234e-22</code>.  So far all I can print is either the short form <code>1.234e-22</code> or <code>0.0</code>!</p>
  
  <p>I would prefer this:</p>
  
  <pre><code>&gt;&gt;&gt; print magic_format(1.234e-22, locale="en_US")
  0.0000000000000000000001234
  &gt;&gt;&gt; print magic_format(1.234e-22, locale="fr_FR")
  0,0000000000000000000001234
  &gt;&gt;&gt; print magic_format(1.234e-22, locale="en_US", group_frac=True)
  0.000,000,000,000,000,000,000,123,400
  &gt;&gt;&gt; print magic_format(1.234e-22, locale="fr_FR", group_frac=True)
  0,000 000 000 000 000 000 000 123 400
  </code></pre>
  
  <p>I can imagine writing a little function that would parse <code>"1.234e-22"</code> and format it nicely, but I would have to know all about the rules of number localization, and I'd rather not reinvent the wheel, Babel is supposed to do that.  What should I do?</p>
  
  <p>Thanks for your help.  :-)</p>