1

I often use this small function eng(x) especially to show big or small numbers in an easy to read way.

This allows me to write"%e" % (number).

I would like to be able to write "%n" % (number) and get the number formatted by this eng(x) function.

Is there a way to do this?

martineau
  • 119,623
  • 25
  • 170
  • 301
Cambium
  • 169
  • 7
  • 2
    See also http://stackoverflow.com/questions/18394385/extending-python-string-formatting-with-custom-conversion-types. You might want to look into using new-style formatting with `str.format()` instead of using `%`-based formatting. – senshin Feb 07 '14 at 07:04
  • "%s" %eng(x) - is that what you need? Not sure though. – Sergii Khaperskov Feb 07 '14 at 07:06
  • 3
    New-style formatting allow you defining custom format specifiers with [`string.Formatter`](http://docs.python.org/2/library/string.html#string.Formatter), so that you could write `myfmt.format('{0:n}', number)` – bereal Feb 07 '14 at 07:09
  • @SergiiKhaperskov That's so obvious, I am not sure how I couldn't think about it myself. Though I think that I will move to new style formatting as it makes sense now that I have seen the answer below. – Cambium Feb 07 '14 at 08:08

2 Answers2

0

You can implement a new number class:

from math import floor, log10
class snumber(float):
        def powerise10(x):
            if x == 0: return 0 , 0 
            Neg = x <0
            if Neg : x = -x
            a = 1.0 * x / 10**(floor(log10(x)))
            b = int(floor(log10(x)))
            if Neg : a = -a
            return a ,b

        def __str__(x):
            a , b = snumber.powerise10(x)
            if -3<b<3: return "%.4g" % x 
            a = a * 10**(b%3)
            b = b - b%3 
            return "%.4g*10^%s" %(a,b)

print "{}".format(snumber(100000))

Gives:

100*10^3
perreal
  • 94,503
  • 21
  • 155
  • 181
0

After further research, I have found how to subclass string.Formatter as per @bereal's suggestion.

import string
from math import floor, log10

class CustFormatter(string.Formatter):
    "Defines special formatting"
    def __init__(self):
        super(CustFormatter, self).__init__()

    def powerise10(self, x):
        if x == 0: return 0, 0
        Neg = x < 0
        if Neg: x = -x
        a = 1.0 * x / 10**(floor(log10(x)))
        b = int(floor(log10(x)))
        if Neg: a = -a
        return a, b

    def eng(self, x):
        a, b = self.powerise10(x)
        if -3 < b < 3: return "%.4g" % x
        a = a * 10**(b%3)
        b = b - b%3
        return "%.4g*10^%s" % (a, b)

    def format_field(self, value, format_string):
      # handle an invalid format
      if format_string == "i":
          return self.eng(value)
      else:
          return super(CustFormatter,self).format_field(value, format_string)

fmt = CustFormatter()
print('{}'.format(0.055412))
print(fmt.format("{0:i} ", 55654654231654))
print(fmt.format("{} ", 0.00254641))

The only problem is that I have partially broken it as for the last line if I don't refer to the variables by position, I get a KeyError.

martineau
  • 119,623
  • 25
  • 170
  • 301
Cambium
  • 169
  • 7
  • This has been solved since then : http://stackoverflow.com/questions/21664318/subclass-string-formatter – Cambium Feb 12 '14 at 14:49