python - 很好地表示 python 中的 float

标签 python floating-point representation significant-digits

<分区>

我想将 float 表示为四舍五入到一定数量有效数字的字符串,并且从不使用指数格式。本质上,我想显示任何 float 并确保它“看起来不错”。

这个问题有几个部分:

  • 我需要能够指定 有效数字的数量。
  • 有效位数 需要是可变的,这不能是 完成 string formatting operator . [edit] 我已被纠正;字符串格式化运算符可以做到这一点。
  • 我需要它按照 a 的方式四舍五入 人会期望,而不是某事 像 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) 打印 float ,其第一个有效数字出现在小数点后第 15 位之后,并且 (2) 不是科学记数法。这样就剩下手动字符串操作了。

下面我使用decimal 模块从 float 中提取十进制数字。 float_to_decimal 函数用于将 float 转换为 Decimal 对象。 decimal.Decimal(str(f)) 的明显方式是错误的,因为 str(f) 可能会丢失有效数字。

float_to_decimaldecimal module's documentation 中提取.

一旦十进制数字作为整数元组获得,下面的代码就做了一件显而易见的事情:砍掉所需数量的有效数字,必要时四舍五入,将数字连接成一个字符串,加上一个符号,根据需要在左侧或右侧放置小数点和零。

在底部你会发现一些我用来测试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)

关于python - 很好地表示 python 中的 float ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2663612/

相关文章:

c - 我应该使用什么类型来表示 C 枚举的二进制?

javascript - 如何在 Node.js 中打印字符串的文字表示?

numbers - 连续 float 之间的间隙

python - 程序流中应该发生的文件写入没有发生

python - 如何解析具有未知属性路径的 JSON?

matlab - 按照我想要的格式设置数字

python - ValueError:无法将字符串转换为 float : '.'

python - Python 性能算法中的不均匀共享

python - 在python lxml中获取无值(value)的元素

c - 在 sigmoid 传递函数中用整数替换 float 学