Python Rounding Inconsistently

时间:2015-07-07 01:48:12

标签: python rounding

如果我告诉Python v.3.4.3,fd_set,那么它输出select()。如果我告诉它round(2.5)那么它也输出2。同样,2提供round(1.5),而round(3.5)也提供4。不过,我需要使用Python来实现一致性。具体来说,它需要在我输入两个整数之间的数字的任何时候进行舍入。所以round(4.5)4,而round(1.5) = 1和往常一样。

我该如何解决这个问题?

编辑:我已经阅读了round(2.5) = 2函数的文档,并了解这是它的预期行为。我的问题是,我怎么能改变这种行为,因为为了我的目的,我需要1.5轮下来。

6 个答案:

答案 0 :(得分:3)

round docs确实解决了舍入浮点数的问题。

您可以使用decimal库来实现您的目标。

from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_DOWN

round(2.675, 2)
# output: 2.67

Decimal('2.675').quantize(Decimal('1.11'), rounding=ROUND_HALF_UP)
# output: 2.68

Decimal('2.5').quantize(Decimal('1.'), rounding=ROUND_HALF_DOWN)
# output: 2

答案 1 :(得分:3)

你想要“向下”,你正在“圆到均匀”。只需手动执行

即可
ceil(x - 0.5)

答案 2 :(得分:2)

与Python 2相比,Python 3使用了不同的舍入行为:它现在使用所谓的"银行家舍入" (Wikipedia):当整数部分为奇数时,该数字从零开始舍入;当整数部分是偶数时,它是否向零舍入。

这样做的原因是为了避免偏差,当.5处的所有值都从零舍入(然后例如求和)。

这是您所看到的行为,实际上是一致的。它可能与你习惯的不同。

答案 3 :(得分:1)

这是很好的记录。根据{{​​3}}:

  

注意浮点数的round()行为可能会令人惊讶:例如,round(2.675,2)给出2.67而不是预期的2.68。这不是一个错误:这是因为大多数小数部分不能完全表示为浮点数。有关详细信息,请参阅Python docs for round

具体而言,这是计算机处理浮点数的一个副作用。

如果您需要更高的精确度,包括不同的舍入,我建议您查看Floating Point Arithmetic: Issues and Limitations。特别感兴趣的是,他们有能力控制the Python Decimal module。看起来您可能需要decimal.ROUND_HALF_DOWN

答案 4 :(得分:0)

我相信我能解决人们遇到的所有舍入错误。我编写了自己的方法,其功能与" round"相同。但实际上是根据具体情况查看最后一位数字和几轮。没有将十进制转换为二进制。它可以处理小数后面的任意数量的数字,它也需要科学记数法(由浮点数输出)。它也不需要任何进口!如果您发现任何无效的案例,请告诉我们。

def Round(Number,digits = 0):
Number_Str = str(Number)
if "e" in Number_Str:
    Number_Str = "%.10f" % float(Number_Str)
if "." in Number_Str:   #If not given an integer
    try:
        Number_List = list(Number_Str)  #All the characters in Number in a list
        Number_To_Check = Number_List[Number_List.index(".") + 1 + digits]  #Gets value to be looked at for rounding.      
        if int(Number_To_Check) >= 5:
            Index_Number_To_Round = Number_List.index(".") + digits
            if Number_List[Index_Number_To_Round] == ".":
                Index_Number_To_Round -= 1
            if int(Number_List[Index_Number_To_Round]) == 9:
                Number_List_Spliced = Number_List[:Number_List.index(".")+digits]
                for index in range(-1,-len(Number_List_Spliced) - 1,-1):
                    if Number_List_Spliced[index] == ".":
                        continue
                    elif int(Number_List_Spliced[index]) == 9:
                        Number_List_Spliced[index] = "0"
                        try:
                            Number_List_Spliced[index-1]
                            continue
                        except IndexError:
                            Number_List_Spliced.insert(0,"1")
                    else:
                        Number_List_Spliced[index] = str(int(Number_List_Spliced[index])+1)
                        break
                FinalNumber = "".join(Number_List_Spliced)
            else:
                Number_List[Index_Number_To_Round] = str(int(Number_List[Index_Number_To_Round])+1)
                FinalNumber = "".join(Number_List[:Index_Number_To_Round + 1])
            return float(FinalNumber)
        else:
            FinalNumber = "".join(Number_List[:Number_List.index(".") + 1 + digits])
            return float(FinalNumber)
    except IndexError:
        return float(Number)
else:   #If given an integer
    return float(Number)

答案 5 :(得分:0)

Python 3提供了IEEE Standard for Floating-Point Arithmetic (IEEE 754)中定义的舍入方法,默认舍入 [1] 指向最接近的数字并最小化累积错误。

在IEEE 754中,定义了5种方法,其中两种用于将舍入到最近的(Python提供第一种round)和三种明确指示的方法(Python trunc模块中有ceilfloorMath

你显然需要有针对性的四舍五入,有一种方法可以告诉Python,你只需要选择。

[1] 由于计算机中浮点数的表示是有限的,因此舍入并不像您想象的那样微不足道,您会感到惊讶!我建议在python 3文档中仔细阅读15. Floating Point Arithmetic: Issues and Limitations