+++ /dev/null
-"""General floating point formatting functions.\r
-\r
-Functions:\r
-fix(x, digits_behind)\r
-sci(x, digits_behind)\r
-\r
-Each takes a number or a string and a number of digits as arguments.\r
-\r
-Parameters:\r
-x: number to be formatted; or a string resembling a number\r
-digits_behind: number of digits behind the decimal point\r
-"""\r
-from warnings import warnpy3k\r
-warnpy3k("the fpformat module has been removed in Python 3.0", stacklevel=2)\r
-del warnpy3k\r
-\r
-import re\r
-\r
-__all__ = ["fix","sci","NotANumber"]\r
-\r
-# Compiled regular expression to "decode" a number\r
-decoder = re.compile(r'^([-+]?)0*(\d*)((?:\.\d*)?)(([eE][-+]?\d+)?)$')\r
-# \0 the whole thing\r
-# \1 leading sign or empty\r
-# \2 digits left of decimal point\r
-# \3 fraction (empty or begins with point)\r
-# \4 exponent part (empty or begins with 'e' or 'E')\r
-\r
-try:\r
- class NotANumber(ValueError):\r
- pass\r
-except TypeError:\r
- NotANumber = 'fpformat.NotANumber'\r
-\r
-def extract(s):\r
- """Return (sign, intpart, fraction, expo) or raise an exception:\r
- sign is '+' or '-'\r
- intpart is 0 or more digits beginning with a nonzero\r
- fraction is 0 or more digits\r
- expo is an integer"""\r
- res = decoder.match(s)\r
- if res is None: raise NotANumber, s\r
- sign, intpart, fraction, exppart = res.group(1,2,3,4)\r
- if sign == '+': sign = ''\r
- if fraction: fraction = fraction[1:]\r
- if exppart: expo = int(exppart[1:])\r
- else: expo = 0\r
- return sign, intpart, fraction, expo\r
-\r
-def unexpo(intpart, fraction, expo):\r
- """Remove the exponent by changing intpart and fraction."""\r
- if expo > 0: # Move the point left\r
- f = len(fraction)\r
- intpart, fraction = intpart + fraction[:expo], fraction[expo:]\r
- if expo > f:\r
- intpart = intpart + '0'*(expo-f)\r
- elif expo < 0: # Move the point right\r
- i = len(intpart)\r
- intpart, fraction = intpart[:expo], intpart[expo:] + fraction\r
- if expo < -i:\r
- fraction = '0'*(-expo-i) + fraction\r
- return intpart, fraction\r
-\r
-def roundfrac(intpart, fraction, digs):\r
- """Round or extend the fraction to size digs."""\r
- f = len(fraction)\r
- if f <= digs:\r
- return intpart, fraction + '0'*(digs-f)\r
- i = len(intpart)\r
- if i+digs < 0:\r
- return '0'*-digs, ''\r
- total = intpart + fraction\r
- nextdigit = total[i+digs]\r
- if nextdigit >= '5': # Hard case: increment last digit, may have carry!\r
- n = i + digs - 1\r
- while n >= 0:\r
- if total[n] != '9': break\r
- n = n-1\r
- else:\r
- total = '0' + total\r
- i = i+1\r
- n = 0\r
- total = total[:n] + chr(ord(total[n]) + 1) + '0'*(len(total)-n-1)\r
- intpart, fraction = total[:i], total[i:]\r
- if digs >= 0:\r
- return intpart, fraction[:digs]\r
- else:\r
- return intpart[:digs] + '0'*-digs, ''\r
-\r
-def fix(x, digs):\r
- """Format x as [-]ddd.ddd with 'digs' digits after the point\r
- and at least one digit before.\r
- If digs <= 0, the point is suppressed."""\r
- if type(x) != type(''): x = repr(x)\r
- try:\r
- sign, intpart, fraction, expo = extract(x)\r
- except NotANumber:\r
- return x\r
- intpart, fraction = unexpo(intpart, fraction, expo)\r
- intpart, fraction = roundfrac(intpart, fraction, digs)\r
- while intpart and intpart[0] == '0': intpart = intpart[1:]\r
- if intpart == '': intpart = '0'\r
- if digs > 0: return sign + intpart + '.' + fraction\r
- else: return sign + intpart\r
-\r
-def sci(x, digs):\r
- """Format x as [-]d.dddE[+-]ddd with 'digs' digits after the point\r
- and exactly one digit before.\r
- If digs is <= 0, one digit is kept and the point is suppressed."""\r
- if type(x) != type(''): x = repr(x)\r
- sign, intpart, fraction, expo = extract(x)\r
- if not intpart:\r
- while fraction and fraction[0] == '0':\r
- fraction = fraction[1:]\r
- expo = expo - 1\r
- if fraction:\r
- intpart, fraction = fraction[0], fraction[1:]\r
- expo = expo - 1\r
- else:\r
- intpart = '0'\r
- else:\r
- expo = expo + len(intpart) - 1\r
- intpart, fraction = intpart[0], intpart[1:] + fraction\r
- digs = max(0, digs)\r
- intpart, fraction = roundfrac(intpart, fraction, digs)\r
- if len(intpart) > 1:\r
- intpart, fraction, expo = \\r
- intpart[0], intpart[1:] + fraction[:-1], \\r
- expo + len(intpart) - 1\r
- s = sign + intpart\r
- if digs > 0: s = s + '.' + fraction\r
- e = repr(abs(expo))\r
- e = '0'*(3-len(e)) + e\r
- if expo < 0: e = '-' + e\r
- else: e = '+' + e\r
- return s + 'e' + e\r
-\r
-def test():\r
- """Interactive test run."""\r
- try:\r
- while 1:\r
- x, digs = input('Enter (x, digs): ')\r
- print x, fix(x, digs), sci(x, digs)\r
- except (EOFError, KeyboardInterrupt):\r
- pass\r