fpformat.py

来自「mallet是自然语言处理、机器学习领域的一个开源项目。」· Python 代码 · 共 143 行

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

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?