-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathFNumber.py
executable file
·150 lines (142 loc) · 5.02 KB
/
FNumber.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/usr/bin/env python
import sys
import math
import string
__author__ = "Scott Hendrickson"
__version__ = "1.0.1"
__email__ = "[email protected]"
class FNumber(object):
"""Float number container produces string formatted number representation with
specified number of significant figures, "," separators for thousands and " "
separators for thousanths. Provides access to string size and offset to
decimal.
"""
# customize separators if necessary
intSeparator = ","
mantissaSeparator = " "
decimalSeparator = "."
def __init__(self, xstring, sf, latex=False, maxColWidth=None):
try:
x = float(xstring)
if math.isnan(x) or math.isinf(x):
raise ValueError
if sf <= 0:
print >>sys.stderr, "What does 0 significant figures mean?"
sys.exit()
except ValueError:
# string
self.sigFigs = 0
self.value = 0.0
self.sign = ""
self.sigValue = 0.0
# max column width only applies to text fields
if maxColWidth is not None and len(xstring) > maxColWidth:
xstring = xstring[0:maxColWidth-3] + "..."
if latex:
self.valueStr = "{%s}"%xstring
else:
self.valueStr = xstring
else:
# store the values
self.sigFigs = int(sf)
self.value = float(x)
# set the sign
if self.value < 0:
self.sign = "-"
else:
self.sign = ""
# calculate the value to desire sig figs
if x <> 0:
decade = int(math.floor(math.log10(abs(x))))
decadeFactor = math.pow(10., self.sigFigs - decade - 1)
self.sigValue = round(float(abs(x)) * decadeFactor, 0) / decadeFactor
else:
decade = 0
decadeFactor = 1
self.sigValue = 0.0
# are any of the digits in int portion significant?
if decade > 0:
intSize = decade + 1
else: # decade <= 0
intSize = 0
#
if intSize > 0: # at least on sig digit left of decimal
if intSize >= self.sigFigs:
mantissaSize = 0
else:
mantissaSize = self.sigFigs - intSize
else: # intSize == 0
mantissaSize = self.sigFigs - decade - 1
#
fmtStr = "%%%d.%dF"%(intSize, mantissaSize)
tmpStr = fmtStr%self.sigValue
tmpList = tmpStr.split(self.decimalSeparator)
intStr = self.sign
intLen = len(tmpList[0])
for i in range(0, intLen):
if (intLen - i)%3 == 0 and i <> 0:
intStr += self.intSeparator
intStr += tmpList[0][i]
mantStr = self.decimalSeparator
for i in range(0, mantissaSize):
if i <> 0 and i%3 == 0 and i <> mantissaSize:
mantStr += self.mantissaSeparator
mantStr += tmpList[1][i]
self.valueStr = intStr + mantStr
if latex:
self.valueStr = self.valueStr.replace(",","")
def size(self):
return len(self.valueStr)
def getOffset(self):
# count, not index
if self.sigFigs != 0:
res = 1 + string.index(self.valueStr, self.decimalSeparator)
else:
res = 1 + self.size()/2
return res
def getRightOffset(self):
return self.size() - self.getOffset()
def getPadded(self, width, offset):
left = offset - self.getOffset()
right = width - left - self.size()
if left < 0 or right < 0:
print >>sys.stderr, "Check you column width and offset. Aborting!"
return " "*left + self.valueStr + " "*right
def __repr__(self):
return self.valueStr
if __name__ == '__main__':
# Simple example of a single column of numbers, aligned on the decimal points
values = [
(1234.234, 1),
(1234.234, 2),
(1234.234, 3),
(123.234, 3),
(123.234, 4),
(1234.234, 4),
(1234.234, 5),
(-1234.234, 5),
(1234.234, 6),
(1234.234, 7),
(1234.234, 9),
(.23456789, 1),
(.23456789, 2),
("hello there", 0),
(-.23456789, 2),
(.23456789, 3),
(.23456789, 4),
(.23456789, 5),
(.0023456789, 3),
(.00023456789, 4),
(.000023456789, 5),
(23456789, 2),
(23456789, 4),
(23456789, 6),
(-23456789, 6),
(23456789.123345, 8),
(23456789.123345, 11),
(1234.234, 0)
]
for f in values:
a = FNumber(f[0], f[1])
#print str(f), a.sigValue, a.size(), a.getOffset(), a
print a.getPadded(30, 15)