2016-11-09 74 views
0

我正在处理一些就地显示的格式化用户存储的浮点数的就地代码。Python格式字符串和浮点表示法

当前实现做到这一点:

"{0:.24f}".format(some_floating_point).rstrip('0') 

这是有道理的和工作得很好大部分。但是当遇到像0.0003这样的价值时,情况就不一样了。

>>> "{0:.24f}".format(0.0003).rstrip('0') 
'0.000299999999999999973719' 

一些进一步的调查表明,Python似乎根据请求的位数改变了底层表示法?

>>> "{0:.15f}".format(0.0003) 
'0.000300000000000' 
>>> "{0:.20f}".format(0.0003) 
'0.00029999999999999997' 

我的假设是单精度vs双精度。

用户输入这些值作为double值存储在数据库中,并且稍后再次呈现表单时,相同的值将在字段中预先填充。因此我需要这些表示的1:1映射。

因此,我的问题是:什么是处理这种行为的优雅,更重要的安全方法?迄今为止我所做的最大努力都涉及到log10,并且不太理想地把它放在很好的位置。

编辑:由于Prune指出价值并没有真正改变,而是由格式完成的舍入将继续导致一组9个变为0(德)。这种行为是有道理的,但解决方案仍在逃避我。

+0

没有一个优雅的解决这一点,它在基地2座10我可以提供答案之间的差别所固有的,但它也需要日志10 - 你需要限制的位数格式要比存储在double中的有效数字少一个。 –

回答

1

您正在接收存储的号码。 0.0003不能完全存储为二进制分数。举例说明:

>>> 0.00029999999999999997 == 0.0003 
True 

打印格式将四舍五入最低位的数字。双精度只会将问题推向右侧。要将问题完全“解决”到base-10眼睛,您需要切换到十进制算术,或者可以为足够接近较简单值的数字构建您自己的字符串处理程序(小数部分为9或0的可疑字符串)。


这是您的一个函数的开始。我用0.0004进行了测试,它的存储量超过了0.0004; 9的情况留作练习:-)。

def str_round(x): 
    size = 6 
    nines = '9'*size 
    zeros = '0'*size 

    str = "{0:.24f}".format(x).rstrip('0') 
    str_len = len(str) 
    print str, str_len 

    if nines in str: 
     # replace leading digit with one more 
     pos = str.index(nines) 
     # ADD CODE HERE 
     # Turn the leading portion into an integer; 
     # increment and convert back to zero-leading string. 
     # Fill out the rest with zeros. 

    elif zeros in str: 
     # Change all trailing digits to 0 
     pos = str.index(zeros) 
     str = str[:pos] + '0'*(str_len - pos) 

    return str 

print str_round(0.0004) 
+0

啊哈,我不知道如何,例如29999可以达到30000.因此,当要求格式化一个不是9的数字时,它会“打破”。出于某种原因,我认为这是在做更复杂的事情。但仍然没有提供很多解决方案。 – Zigsaz