Initial commit. Please see the README
[golden_search.git] / number.py
blob22d28b166cce63f7024b7718447b814220dd3e00
1 # -*- coding: utf-8 -*-
3 import math
5 from exc import IncompatibleUnits
6 import operators
8 def units_op(u1, u2, op):
9 u = {}
10 for k in u1.viewkeys() | u2.viewkeys():
11 v1, v2 = u1.get(k, 0), u2.get(k, 0)
12 v = op( v1, v2 )
13 if v != 0:
14 u[k] = v
15 return u
17 def units_diff(u1, u2):
18 return units_op(u1, u2, lambda x, y : x - y)
20 def units_join(u1, u2):
21 return units_op(u1, u2, lambda x, y : x + y)
23 class Number:
24 def __init__(self, value, sdsq=0, units=None, string='', parents=None):
25 if units == None:
26 units = {}
28 self.value = float(value)
29 self.sdsq = sdsq
30 self.units = units
31 self.string = string
32 self.parents = parents
34 def __add__(self, other):
35 return operators.Plus()((self, other))
37 def __sub__(self, other):
38 return operators.Minus()((self, other))
40 def __mul__(self, other):
41 return operators.Mult()((self, other))
43 def __rmul__(self, other):
44 assert isinstance(other, int) or isinstance(other, float)
46 return operators.Times(other)((self,))
48 def __div__(self, other):
49 return operators.Div()((self, other))
51 def getDifference(self, other):
52 # TODO lip??
53 if self.getUnits() != other.getUnits():
54 raise IncompatibleUnits
56 assert self.sdsq == 0
58 diff = abs(1.0 - other.getValue() / self.getValue())
60 op = other.getSdPerc()
61 if diff < op:
62 return op
64 return diff
66 def getValue(self):
67 return self.value
69 def getSdSquare(self):
70 return self.sdsq
72 def getSd(self):
73 return math.sqrt(self.getSdSquare())
75 def getSdPerc(self):
76 return self.getSd() / abs(self.getValue())
78 def getUnits(self):
79 return self.units
81 def strUnits(self):
82 l=[]
83 for key in sorted(self.units.keys()):
84 l.append(key)
85 v = self.units[key]
86 if v != 1:
87 l.append( '^%d'%(v,))
88 return ''.join(l)
90 def longStr(self):
91 return self.headStr() + " = " + str(self)
93 def headStr(self):
94 return u'%.4f ± %.4f %s'%(self.getValue(), self.getSd(), self.strUnits())
96 def __str__(self):
97 s = self.string
98 if self.parents:
99 s += "(%s)"%(', '.join(map(str, self.parents), ), )
100 return s