我想代表着一个浮点数,作为一串四舍五入到一些数量的显着位的数字,而不使用指数的格式。基本上,我想显示任何浮点数,并确保它"看起来好"。

有几件这样的问题:

  • 我需要能够指定 若干重要数字。
  • 这些重要数字 需要变量,这不可能 做的 串格式化 操作员.[编辑]我已经修正;串的格式操作人员可以做到这一点。
  • 我需要它是圆形的方式 人期望的,不是东西 像1.999999999999

我已经想通了,这样做的一种方式,虽然它看起来像一个工作轮和它不是完美的。(最高精度为15位有效数字。)

>>> def f(number, sigfig):
    return ("%.15f" % (round(number, int(-1 * floor(log10(number)) + (sigfig - 1))))).rstrip("0").rstrip(".")

>>> print f(0.1, 1)
0.1
>>> print f(0.0000000000368568, 2)
0.000000000037
>>> print f(756867, 3)
757000

有没有更好的方式做到这一点?为什么不Python有一个内置的功能吗?

有帮助吗?

解决方案

它似乎没有内在的串的格式招它可以让你(1)印浮子的第一个重要的数字后显示15小数位和(2)不在科学符号。因此,叶子的手册串的操纵。

下面我使用 decimal 模块中提取的小数位数字浮动。的 float_to_decimal 功能用于转换的浮到一个 Decimal 对象。显而易见的方法 decimal.Decimal(str(f)) 是错误的,因为 str(f) 可能会失去重要的数字。

float_to_decimal 是从 十进制的模块的文件.

一旦小数位数是得到作为一个组整数,以下代码没有显而易见的事情:砍掉所需数量的sigificant数字,圆形,如果有必要,加入该数字连成一串,粘在一个标志,地方的小数点和零左或右。

在底部,你会找到一些情况下,我用来测试 f 功能。

import decimal

def float_to_decimal(f):
    # http://docs.python.org/library/decimal.html#decimal-faq
    "Convert a floating point number to a Decimal with no loss of information"
    n, d = f.as_integer_ratio()
    numerator, denominator = decimal.Decimal(n), decimal.Decimal(d)
    ctx = decimal.Context(prec=60)
    result = ctx.divide(numerator, denominator)
    while ctx.flags[decimal.Inexact]:
        ctx.flags[decimal.Inexact] = False
        ctx.prec *= 2
        result = ctx.divide(numerator, denominator)
    return result 

def f(number, sigfig):
    # http://stackoverflow.com/questions/2663612/nicely-representing-a-floating-point-number-in-python/2663623#2663623
    assert(sigfig>0)
    try:
        d=decimal.Decimal(number)
    except TypeError:
        d=float_to_decimal(float(number))
    sign,digits,exponent=d.as_tuple()
    if len(digits) < sigfig:
        digits = list(digits)
        digits.extend([0] * (sigfig - len(digits)))    
    shift=d.adjusted()
    result=int(''.join(map(str,digits[:sigfig])))
    # Round the result
    if len(digits)>sigfig and digits[sigfig]>=5: result+=1
    result=list(str(result))
    # Rounding can change the length of result
    # If so, adjust shift
    shift+=len(result)-sigfig
    # reset len of result to sigfig
    result=result[:sigfig]
    if shift >= sigfig-1:
        # Tack more zeros on the end
        result+=['0']*(shift-sigfig+1)
    elif 0<=shift:
        # Place the decimal point in between digits
        result.insert(shift+1,'.')
    else:
        # Tack zeros on the front
        assert(shift<0)
        result=['0.']+['0']*(-shift-1)+result
    if sign:
        result.insert(0,'-')
    return ''.join(result)

if __name__=='__main__':
    tests=[
        (0.1, 1, '0.1'),
        (0.0000000000368568, 2,'0.000000000037'),           
        (0.00000000000000000000368568, 2,'0.0000000000000000000037'),
        (756867, 3, '757000'),
        (-756867, 3, '-757000'),
        (-756867, 1, '-800000'),
        (0.0999999999999,1,'0.1'),
        (0.00999999999999,1,'0.01'),
        (0.00999999999999,2,'0.010'),
        (0.0099,2,'0.0099'),         
        (1.999999999999,1,'2'),
        (1.999999999999,2,'2.0'),           
        (34500000000000000000000, 17, '34500000000000000000000'),
        ('34500000000000000000000', 17, '34500000000000000000000'),  
        (756867, 7, '756867.0'),
        ]

    for number,sigfig,answer in tests:
        try:
            result=f(number,sigfig)
            assert(result==answer)
            print(result)
        except AssertionError:
            print('Error',number,sigfig,result,answer)

其他提示

如果你想浮点精度,需要使用 decimal 模块,该模块的一部分 蟒蛇的标准图书馆:

>>> import decimal
>>> d = decimal.Decimal('0.0000000000368568')
>>> print '%.15f' % d
0.000000000036857

这是一段代码格式的价值根据错误的酒吧。

from math import floor, log10, round

def sigfig3(v, errplus, errmin):
    i = int(floor(-log10(max(errplus,errmin)) + 2))
    if i > 0:
        fmt = "%%.%df" % (i)
        return "{%s}^{%s}_{%s}" % (fmt % v,fmt % errplus, fmt % errmin)
    else:
        return "{%d}^{%d}_{%d}" % (round(v, i),round(errplus, i), numpy.round(i))

实例:

5268685 (+1463262,-2401422) becomes 5300000 (+1500000,-2400000)
0.84312 +- 0.173124 becomes 0.84 +- 0.17

任意的精彩车是需要正确回答这个问题。因此,使用 小数点模块 是必须的。有没有方法来转换一个小数字符串而不使用指数的格式(部分原来的问题),因此我写了一个功能要做的只是:

def removeExponent(decimal):
    digits = [str(n) for n in decimal.as_tuple().digits]
    length = len(digits)
    exponent = decimal.as_tuple().exponent
    if length <= -1 * exponent:
        zeros = -1 * exponent - length
        digits[0:0] = ["0."] + ["0"] * zeros
    elif 0 < -1 * exponent < length:
        digits.insert(exponent, ".")
    elif 0 <= exponent:
        digits.extend(["0"] * exponent)
    sign = []
    if decimal.as_tuple().sign == 1:
        sign = ["-"]
    print "".join(sign + digits)

问题是试图轮到重大的数字。十进制的"量化()"方法不会的圆形,高于小数点的"round()"功能总是返回浮动。我不知道如果这些都是错误的,但它意味着,只有这样,才能轮无限的精确度浮点数是分析它作为一个列表或串做的四舍五入。换句话说,没有理智的回答这个问题。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top