symbian-qemu-0.9.1-12/python-2.6.1/Lib/fpformat.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 """General floating point formatting functions.
       
     2 
       
     3 Functions:
       
     4 fix(x, digits_behind)
       
     5 sci(x, digits_behind)
       
     6 
       
     7 Each takes a number or a string and a number of digits as arguments.
       
     8 
       
     9 Parameters:
       
    10 x:             number to be formatted; or a string resembling a number
       
    11 digits_behind: number of digits behind the decimal point
       
    12 """
       
    13 from warnings import warnpy3k
       
    14 warnpy3k("the fpformat module has been removed in Python 3.0", stacklevel=2)
       
    15 del warnpy3k
       
    16 
       
    17 import re
       
    18 
       
    19 __all__ = ["fix","sci","NotANumber"]
       
    20 
       
    21 # Compiled regular expression to "decode" a number
       
    22 decoder = re.compile(r'^([-+]?)0*(\d*)((?:\.\d*)?)(([eE][-+]?\d+)?)$')
       
    23 # \0 the whole thing
       
    24 # \1 leading sign or empty
       
    25 # \2 digits left of decimal point
       
    26 # \3 fraction (empty or begins with point)
       
    27 # \4 exponent part (empty or begins with 'e' or 'E')
       
    28 
       
    29 try:
       
    30     class NotANumber(ValueError):
       
    31         pass
       
    32 except TypeError:
       
    33     NotANumber = 'fpformat.NotANumber'
       
    34 
       
    35 def extract(s):
       
    36     """Return (sign, intpart, fraction, expo) or raise an exception:
       
    37     sign is '+' or '-'
       
    38     intpart is 0 or more digits beginning with a nonzero
       
    39     fraction is 0 or more digits
       
    40     expo is an integer"""
       
    41     res = decoder.match(s)
       
    42     if res is None: raise NotANumber, s
       
    43     sign, intpart, fraction, exppart = res.group(1,2,3,4)
       
    44     if sign == '+': sign = ''
       
    45     if fraction: fraction = fraction[1:]
       
    46     if exppart: expo = int(exppart[1:])
       
    47     else: expo = 0
       
    48     return sign, intpart, fraction, expo
       
    49 
       
    50 def unexpo(intpart, fraction, expo):
       
    51     """Remove the exponent by changing intpart and fraction."""
       
    52     if expo > 0: # Move the point left
       
    53         f = len(fraction)
       
    54         intpart, fraction = intpart + fraction[:expo], fraction[expo:]
       
    55         if expo > f:
       
    56             intpart = intpart + '0'*(expo-f)
       
    57     elif expo < 0: # Move the point right
       
    58         i = len(intpart)
       
    59         intpart, fraction = intpart[:expo], intpart[expo:] + fraction
       
    60         if expo < -i:
       
    61             fraction = '0'*(-expo-i) + fraction
       
    62     return intpart, fraction
       
    63 
       
    64 def roundfrac(intpart, fraction, digs):
       
    65     """Round or extend the fraction to size digs."""
       
    66     f = len(fraction)
       
    67     if f <= digs:
       
    68         return intpart, fraction + '0'*(digs-f)
       
    69     i = len(intpart)
       
    70     if i+digs < 0:
       
    71         return '0'*-digs, ''
       
    72     total = intpart + fraction
       
    73     nextdigit = total[i+digs]
       
    74     if nextdigit >= '5': # Hard case: increment last digit, may have carry!
       
    75         n = i + digs - 1
       
    76         while n >= 0:
       
    77             if total[n] != '9': break
       
    78             n = n-1
       
    79         else:
       
    80             total = '0' + total
       
    81             i = i+1
       
    82             n = 0
       
    83         total = total[:n] + chr(ord(total[n]) + 1) + '0'*(len(total)-n-1)
       
    84         intpart, fraction = total[:i], total[i:]
       
    85     if digs >= 0:
       
    86         return intpart, fraction[:digs]
       
    87     else:
       
    88         return intpart[:digs] + '0'*-digs, ''
       
    89 
       
    90 def fix(x, digs):
       
    91     """Format x as [-]ddd.ddd with 'digs' digits after the point
       
    92     and at least one digit before.
       
    93     If digs <= 0, the point is suppressed."""
       
    94     if type(x) != type(''): x = repr(x)
       
    95     try:
       
    96         sign, intpart, fraction, expo = extract(x)
       
    97     except NotANumber:
       
    98         return x
       
    99     intpart, fraction = unexpo(intpart, fraction, expo)
       
   100     intpart, fraction = roundfrac(intpart, fraction, digs)
       
   101     while intpart and intpart[0] == '0': intpart = intpart[1:]
       
   102     if intpart == '': intpart = '0'
       
   103     if digs > 0: return sign + intpart + '.' + fraction
       
   104     else: return sign + intpart
       
   105 
       
   106 def sci(x, digs):
       
   107     """Format x as [-]d.dddE[+-]ddd with 'digs' digits after the point
       
   108     and exactly one digit before.
       
   109     If digs is <= 0, one digit is kept and the point is suppressed."""
       
   110     if type(x) != type(''): x = repr(x)
       
   111     sign, intpart, fraction, expo = extract(x)
       
   112     if not intpart:
       
   113         while fraction and fraction[0] == '0':
       
   114             fraction = fraction[1:]
       
   115             expo = expo - 1
       
   116         if fraction:
       
   117             intpart, fraction = fraction[0], fraction[1:]
       
   118             expo = expo - 1
       
   119         else:
       
   120             intpart = '0'
       
   121     else:
       
   122         expo = expo + len(intpart) - 1
       
   123         intpart, fraction = intpart[0], intpart[1:] + fraction
       
   124     digs = max(0, digs)
       
   125     intpart, fraction = roundfrac(intpart, fraction, digs)
       
   126     if len(intpart) > 1:
       
   127         intpart, fraction, expo = \
       
   128             intpart[0], intpart[1:] + fraction[:-1], \
       
   129             expo + len(intpart) - 1
       
   130     s = sign + intpart
       
   131     if digs > 0: s = s + '.' + fraction
       
   132     e = repr(abs(expo))
       
   133     e = '0'*(3-len(e)) + e
       
   134     if expo < 0: e = '-' + e
       
   135     else: e = '+' + e
       
   136     return s + 'e' + e
       
   137 
       
   138 def test():
       
   139     """Interactive test run."""
       
   140     try:
       
   141         while 1:
       
   142             x, digs = input('Enter (x, digs): ')
       
   143             print x, fix(x, digs), sci(x, digs)
       
   144     except (EOFError, KeyboardInterrupt):
       
   145         pass