Xorn
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages
fixednum.py
Go to the documentation of this file.
1 # Copyright (C) 2013-2016 Roland Lutz
2 #
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 
17 ## \namespace xorn.fixednum
18 ## Fixed-point numbers.
19 #
20 # This module provides formatting and parsing functions for
21 # fixed-point number notation.
22 
23 ## Convert an integer to its fixed-point string representation.
24 #
25 # \param [in] x value to convert (must be either \c int
26 # or \c long)
27 # \param [in] decimal_digits number of decimal digits used in the
28 # notation
29 #
30 # TODO: For efficiency reasons, this should be ported to C.
31 
32 def format(x, decimal_digits):
33  if not isinstance(x, int) and not isinstance(x, long):
34  raise TypeError, 'invalid argument type (must be int or long)'
35  if not isinstance(decimal_digits, int):
36  raise TypeError, 'number of decimals must be an integer'
37  if decimal_digits < 0:
38  raise ValueError, 'number of decimals must be non-negative'
39 
40  s = str(x)
41 
42  if s[0] == '-':
43  sign = '-'
44  s = s[1:]
45  else:
46  sign = ''
47 
48  if decimal_digits == 0:
49  if s == '0':
50  return '0' # signless zero
51  return sign + s
52 
53  if len(s) < decimal_digits:
54  s = '0' * (decimal_digits - len(s)) + s
55  s0 = s[:-decimal_digits]
56  s1 = s[-decimal_digits:]
57 
58  if s1 == '0' * decimal_digits:
59  if not s0:
60  return '0' # signless zero
61  return sign + s0
62  else:
63  return sign + s0 + '.' + s1.rstrip('0')
64 
65 ## Convert a fixed-point string representation to an integer.
66 #
67 # \param [in] x value to convert (must be either \c str
68 # or \c unicode)
69 # \param [in] decimal_digits number of decimal digits used in the
70 # notation
71 #
72 # TODO: For efficiency reasons, this should be ported to C.
73 
74 def parse(s, decimal_digits):
75  if not isinstance(s, str) and not isinstance(s, unicode):
76  raise TypeError, 'invalid argument type (must be str or unicode)'
77  if not isinstance(decimal_digits, int):
78  raise TypeError, 'number of decimals must be an integer'
79  if decimal_digits < 0:
80  raise ValueError, 'number of decimals must be non-negative'
81 
82  if s and s[0] == '-':
83  sign = -1
84  s = s[1:]
85  else:
86  sign = 1
87 
88  if not s:
89  raise ValueError
90 
91  if decimal_digits == 0:
92  if '.' in s:
93  raise ValueError
94  s0 = s
95  s1 = ''
96  else:
97  try:
98  pos = s.index('.')
99  except ValueError:
100  s0 = s
101  s1 = ''
102  else:
103  s0 = s[:pos]
104  s1 = s[pos + 1:]
105  if not s0 and not s1:
106  raise ValueError
107  if len(s1) < decimal_digits:
108  s1 = s1 + (decimal_digits - len(s1)) * '0'
109 
110  if len(s1) > decimal_digits:
111  raise ValueError
112 
113  for c in s0 + s1:
114  if c not in '0123456789':
115  raise ValueError
116 
117  if not s0:
118  s0 = '0'
119  if not s1:
120  s1 = '0'
121 
122  return sign * (int(s0) * 10 ** decimal_digits + int(s1))
def parse
Convert a fixed-point string representation to an integer.
Definition: fixednum.py:74
def format
Convert an integer to its fixed-point string representation.
Definition: fixednum.py:32