当插入字符串时,转换为2.dp的Float将恢复为原始的小数位数

时间:2013-10-16 22:42:28

标签: python python-2.7 if-statement format decimal

我创建了以下代码片段,我正在尝试将我的5 dp DNumber转换为2 dp,并将其插入到字符串中。然而,我尝试使用哪种方法,似乎总是将DNumber恢复为原始的小数位数(5)

以下代码段:

if key == (1, 1):
    DNumber = '{r[csvnum]}'.format(r=row) 
    # returns 7.65321
    DNumber = """%.2f""" % (float(DNumber))
    # returns 7.65
    Check2 = False              
    if DNumber:
        if DNumber <= float(8):
            Check2 = True                    
        if Check2:
            print DNumber 
            # returns 7.65
            string = 'test {r[csvhello]} TESTHERE test'.format(r=row).replace("TESTHERE", str("""%.2f""" % (float(gtpe)))) 
# returns: test Hello 7.65321 test
            string = 'test {r[csvhello]} TESTHERE test'.format(r=row).replace("TESTHERE", str(DNumber))
# returns: test Hello 7.65321 test

我希望它会回归:test Hello 7.65 test

有关替代方法的任何想法或建议吗?

3 个答案:

答案 0 :(得分:4)

看起来你希望将float转换为2位小数位的字符串,然后再转换为float会给你一个2位小数位的浮点数。

第一个问题是您的代码实际上并没有在任何地方执行此操作。如果你这样做了,你会得到非常接近7.65的东西,而不是7.65321

但更大的问题是,你要做的事情没有任何意义。无论如何,浮点数总是有53个二进制数字。如果你将它四舍五入到两位小数(无论你怎么做,包括转换为字符串和返回),你实际得到的是一个舍入为两位小数然后四舍五入为53位二进制数的浮点数。最近的float7.65并不完全是7.65,而是7.650000000000000355271368。*所以,这就是你最终的结果。并且没有办法解决这个问题;它是float存储方式所固有的。

但是,您可以使用不同的类型:decimal.Decimal。例如:

>>> f = 7.65321
>>> s = '%.2f' % f
>>> d = decimal.Decimal(s)
>>> f, s, d
(7.65321, '7.65', Decimal('7.65'))

或者,当然,你可以传递一个字符串而不是一个浮点数(因为你已经意外地在你的代码中做了),或者你可能记得每次你想要使用.2f格式输出它。


作为旁注,由于您的DNumber最终为字符串,因此该行没有做任何有用的事情:

if DNumber <= 8:

在Python 2.x中,比较不同类型的两个值会给出一致但任意且无意义的答案。使用CPython 2.x时,它始终为False。**在不同的Python 2.x实现中,它可能会有所不同。在Python 3.x中,它引发了TypeError

将其改为此并没有任何帮助:

if DNumber <= float(8):

现在,您不是将strint进行比较,而是将strfloat进行比较。这完全没有意义,遵循完全相同的规则。 (另外,float(8)8.0的含义相同,但可读性较低且可能较慢。)

就此而言:

if DNumber:

......总是如此。对于数字,if foo检查它是否为非零。这对于float值来说是个坏主意(你应该检查它是否在0的绝对或相对误差范围内)。但同样,你没有float值;你有str。对于字符串,if foo检查字符串是否为非空。因此,即使您从0开始,您的字符串"0.00"也将成为现实。


*我假设您在使用CPython的平台上使用IEEE-754 double作为其C double类型,并且所有那些在字符串和浮点数之间来回的额外转换都不是'引入任何其他错误。

**规则略有简化:如果你比较两个数字,它们会被转换成一种可以同时容纳它们的类型;否则,如果任一值为None,则它更小;否则,如果任一值是一个数字,它就更小;否则,无论哪个类型的字母顺序都是较早的名称。

答案 1 :(得分:1)

我认为您正在尝试执行以下操作 - 将格式与getter结合使用:

>>> a = 123.456789
>>> row = {'csvnum': a}
>>> print 'test {r[csvnum]:.2f} hello'.format(r=row)
test 123.46 hello

答案 2 :(得分:0)

如果您的号码是7后跟五位数,您可能想尝试:

print "%r" % float(str(x)[:4])

其中x是有问题的浮点数。 例如:

>>>x = 1.11111
>>>print "%r" % float(str(x)[:4])
>>>1.11