浮点到字符串往返测试

时间:2015-09-20 23:31:29

标签: python floating-point rounding precision ieee-754

我相信17个小数位应该足以正确表示一个8字节的浮点数,这样它就是往返安全的(转换成字符串然后返回而没有任何损失)。

但是在这个测试中,数字可以高达23,如果你增加迭代次数可能会更高。

这是一个有缺陷的测试吗?为什么? 那么如何确保Python中浮点数的往返完整性?

def TestLoop():
    sFormat = ''
    success = True
    ff = [1.0/i for i in range(1,10000000)]
    for n in range(17, 31):
        sFormat = '{{:.{:d}f}}'.format(n)
        success = True
        for f in ff:
            if f != float(sFormat.format(f)):
                success = False
                break
        if success:
            return(n)
    return(-1)

n = TestLoop()   
print('Lossless with ', n, ' decimal places.')

If an IEEE 754 double precision is converted to a decimal string with at least 17 significant digits and then converted back to double, then the final number must match the original.

1 个答案:

答案 0 :(得分:2)

在我原来的测试中,我操作的是小数字,所以有很多前导零,这些都不是有效数字。浮点数需要17个显着数字才能正确表示。通过改变这样的一行,我使数字更大,并且能够在小数点后只有16位数成功。

ff = [10000000.0/i for i in range(1,10000000)]

最好的方法似乎是根本不使用format(),而是使用repr()str()代替。
这段代码成功了:

def TestLoop():
    for i in range(1, 10000000):
        f = 1.0 / i
        if f != float(repr(f)):
            print('Failed.')
            return
    print('Succeeded.')
    return

TestLoop()

另一种方法是在小数点后使用17位数,但使用g格式化程序而不是f。这使用指数,因此消除了前导零。

if f != float('{:.17g}'.format(f)):
相关问题