File indexing completed on 2026-04-09 07:48:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 """
0022 """
0023
0024 import numpy as np
0025 import os, logging, re
0026 from collections import OrderedDict as odict
0027
0028 log = logging.getLogger(__name__)
0029
0030 class Num(object):
0031 """
0032 ::
0033
0034 In [19]: np.power( 10, np.arange(10) )
0035 Out[19]: array([ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000])
0036
0037 In [69]: map(Num.String, a )
0038 Out[69]: ['1', '10', '100', '1k', '10k', '100k', '1M', '10M', '100M', '1B']
0039
0040 """
0041 Ptn0 = re.compile("^(?P<nz>[\d]+?)(?P<zz>[0]*)$")
0042 Ptn = re.compile("^(?P<num>\d+)(?P<unit>[kM]*)$")
0043 Units = { "":1, "k":1000, "M":1000000 }
0044 Pow10 = None
0045
0046 @classmethod
0047 def OrigShape(cls, a):
0048 return a.origshape() if hasattr(a, 'origshape') else "-"
0049
0050 @classmethod
0051 def Init(cls):
0052 r = odict()
0053 r[ "0"] = (0,"")
0054 r[ "1"] = (1,"")
0055 r[ "10"] = (10,"")
0056 r[ "100"] = (100,"")
0057 r[ "1,000"] = (1,"k")
0058 r[ "10,000"] = (10,"k")
0059 r[ "100,000"] = (100,"k")
0060 r[ "1,000,000"] = (1,"M")
0061 r[ "10,000,000"] = (10,"M")
0062 r[ "100,000,000"] = (100,"M")
0063 r["1,000,000,000"] = (1,"B")
0064
0065 d = odict()
0066 for k,v in r.items():
0067 d[int(k.replace(",",""))] = v
0068 pass
0069 return d
0070
0071 @classmethod
0072 def Int(cls, s):
0073 """
0074 :param s: string representation of integer eg "1","10","100","1k","10k","100k","1M",...
0075 :return i: the integer
0076 """
0077 if s.find(",") > -1:
0078 ret = tuple(map(cls.Int, s.split(",")))
0079 else:
0080 m = cls.Ptn.match(s)
0081 if m is None:
0082 return int(s)
0083 pass
0084 d = m.groupdict()
0085 n = int(d["num"])
0086 u = cls.Units[d["unit"]]
0087 i = n*u
0088 ret = i
0089 pass
0090 return ret
0091
0092
0093 @classmethod
0094 def String(cls, i):
0095 """
0096 :param i: integer or tuple of integers
0097 :return s: summary string
0098
0099 Summarize large power of 10 numbers to make them easy to read without counting zeros
0100 """
0101 if cls.Pow10 is None: cls.Pow10 = cls.Init()
0102
0103 if type(i) in [ int, np.int64, np.int32 ]:
0104
0105 m0 = cls.Ptn0.match(str(i))
0106 d0 = m0.groupdict() if m0 else None
0107 if d0:
0108 nz = int(d0["nz"])
0109 zz = int("1"+d0["zz"])
0110 n,u = cls.Pow10[zz]
0111 nnz = n*nz
0112 ret = "%d%s" % (nnz, u)
0113 else:
0114 ret = str(i)
0115 pass
0116 return ret
0117
0118 elif type(i) is tuple:
0119 ret = ",".join( map(lambda _:cls.String(_), list(i) ))
0120 elif type(i) is type(None):
0121 ret = "-"
0122 else:
0123 assert 0, (i, type(i))
0124 ret = "-"
0125 pass
0126 return ret
0127
0128
0129
0130 slice_ = lambda s:slice(*map(lambda _:Num.Int(_) if len(_) > 0 else None,s.split(":")))
0131 _slice = lambda s:":".join(map(lambda _:Num.String(_) if not _ is None else "", (s.start,s.stop,s.step)))
0132
0133
0134 def test_roundtrip():
0135 for i in [(20000000, 4, 4), 200000000, 2, 20, 30,300,3000,30000,100000,1000000,10000000,101000]:
0136 s = Num.String(i)
0137 i2 = Num.Int(s)
0138 print(" i %20r Num.String %20r Num.Int %10r " % ( i, s, i2 ))
0139 assert i == i2, ( i, s, i2)
0140 pass
0141
0142
0143
0144
0145 if __name__ == '__main__':
0146 pass
0147 test_roundtrip()
0148
0149