Python round()不';我似乎不太明白

Python round()不';我似乎不太明白,python,floating-point,rounding,Python,Floating Point,Rounding,该函数的文档说明,您向它传递一个数字,并将超过小数点的位置四舍五入。因此,它应该这样做: 但是,事实上,好的古老的浮点奇观悄然而至,你会得到: 5.5999999999999996 为了使用UI,我需要显示5.6。我浏览了一下互联网,发现这取决于我对Python的实现。不幸的是,这在我的Windows开发机器和我尝试过的每台Linux服务器上都会发生 除了创建我自己的循环库,还有什么方法可以解决这个问题吗?关于: round(n,1)+epsilon 我无法控制它的存储方式,但至少格式正确:

该函数的文档说明,您向它传递一个数字,并将超过小数点的位置四舍五入。因此,它应该这样做:

但是,事实上,好的古老的浮点奇观悄然而至,你会得到:

5.5999999999999996
为了使用UI,我需要显示
5.6
。我浏览了一下互联网,发现这取决于我对Python的实现。不幸的是,这在我的Windows开发机器和我尝试过的每台Linux服务器上都会发生

除了创建我自己的循环库,还有什么方法可以解决这个问题吗?

关于:

round(n,1)+epsilon

我无法控制它的存储方式,但至少格式正确:

'%.1f' % round(n, 1) # Gives you '5.6'

您可以将数据类型切换为整数:

>>> n = 5.59
>>> int(n * 10) / 10.0
5.5
>>> int(n * 10 + 0.5)
56
然后通过插入区域设置的十进制分隔符来显示数字


但是,更好。

您可以使用字符串格式操作符
%
,类似于sprintf

mystring = "%.2f" % 5.5999

如果执行
str(轮(n,1))
而不是只执行
round(n,1)
浮点数学容易出现轻微但令人恼火的精度错误,则会得到'5.6'。如果您可以使用整数或定点,则可以保证精度。

printf吸盘

print '%.1f' % 5.59  # returns 5.6

即使不必舍入,格式也能正确工作:

"%.1f" % n
round(5.59,1)
运行良好。问题是5.6不能用二进制浮点精确表示

>>> 5.6
5.5999999999999996
>>> 
正如Vinko所说,您可以使用字符串格式对显示进行舍入

如果您需要,Python有一个功能

“十进制”是基于浮点的 与人一起设计的模型 在心里,必然有一个 首要指导原则- 计算机必须提供一种算法 这与 人们学习的算术 学校。”——摘自小数点 算术规范

可以表示十进制数 确切地相比之下,数字像1.1 和2.2没有精确的 二进制浮点表示法 指向最终用户通常不会这样做 期望1.1+2.2显示为 3.30000000000000003,与二进制浮点相同

>>> 5.6
5.5999999999999996
>>> 

Decimal提供了一种操作,使编写需要浮点操作的应用程序变得容易,并且还需要以人类可读的格式显示这些结果,例如会计。

如果使用Decimal模块,则无需使用“round”函数即可近似计算。以下是我一直在使用的舍入方法,尤其是在编写货币应用程序时:

from decimal import Decimal, ROUND_UP

Decimal(str(16.2)).quantize(Decimal('.01'), rounding=ROUND_UP)

这将返回一个16.20的十进制数。

这确实是一个大问题。请尝试以下代码:

print "%.2f" % (round((2*4.4+3*5.6+3*4.4)/8,2),)
显示为4.85。然后你会:

print "Media = %.1f" % (round((2*4.4+3*5.6+3*4.4)/8,1),)
显示为4.8。您是否手工计算准确答案为4.85,但如果您尝试:

print "Media = %.20f" % (round((2*4.4+3*5.6+3*4.4)/8,20),)
您可以看到真相:浮点存储为分母为二的幂的分数的最近有限和。

非常有效

format(5.59, '.1f') # to display
float(format(5.59, '.1f')) #to round
我正在做:

int(round( x , 0))
在这种情况下,我们首先在单位级别正确地进行四舍五入,然后转换为整数以避免打印浮点

所以


我认为这个答案比格式化字符串更有效,而且对我来说,使用round函数也更有意义。

这里是我看到round失败的地方。如果你想把这两个数字四舍五入到小数点后一位呢? 23.45 23.55 我所受的教育是,通过四舍五入,你应该得到: 23.4 23.6 “规则”是,如果前面的数字是奇数,则应向上取整,如果前面的数字是偶数,则不应向上取整。 python中的round函数只是截断5。

代码:

x1 = 5.63
x2 = 5.65
print(float('%.2f' % round(x1,1)))  # gives you '5.6'
print(float('%.2f' % round(x2,1)))  # gives you '5.7'
输出:

5.6
5.7

问题只出现在最后一位为5时。例如,0.045在内部存储为0.044999999999。。。您只需将最后一位数字增加到6并四舍五入即可。这将为您提供所需的结果

import re


def custom_round(num, precision=0):
    # Get the type of given number
    type_num = type(num)
    # If the given type is not a valid number type, raise TypeError
    if type_num not in [int, float, Decimal]:
        raise TypeError("type {} doesn't define __round__ method".format(type_num.__name__))
    # If passed number is int, there is no rounding off.
    if type_num == int:
        return num
    # Convert number to string.
    str_num = str(num).lower()
    # We will remove negative context from the number and add it back in the end
    negative_number = False
    if num < 0:
        negative_number = True
        str_num = str_num[1:]
    # If number is in format 1e-12 or 2e+13, we have to convert it to
    # to a string in standard decimal notation.
    if 'e-' in str_num:
        # For 1.23e-7, e_power = 7
        e_power = int(re.findall('e-[0-9]+', str_num)[0][2:])
        # For 1.23e-7, number = 123
        number = ''.join(str_num.split('e-')[0].split('.'))
        zeros = ''
        # Number of zeros = e_power - 1 = 6
        for i in range(e_power - 1):
            zeros = zeros + '0'
        # Scientific notation 1.23e-7 in regular decimal = 0.000000123
        str_num = '0.' + zeros + number
    if 'e+' in str_num:
        # For 1.23e+7, e_power = 7
        e_power = int(re.findall('e\+[0-9]+', str_num)[0][2:])
        # For 1.23e+7, number_characteristic = 1
        # characteristic is number left of decimal point.
        number_characteristic = str_num.split('e+')[0].split('.')[0]
        # For 1.23e+7, number_mantissa = 23
        # mantissa is number right of decimal point.
        number_mantissa = str_num.split('e+')[0].split('.')[1]
        # For 1.23e+7, number = 123
        number = number_characteristic + number_mantissa
        zeros = ''
        # Eg: for this condition = 1.23e+7
        if e_power >= len(number_mantissa):
            # Number of zeros = e_power - mantissa length = 5
            for i in range(e_power - len(number_mantissa)):
                zeros = zeros + '0'
            # Scientific notation 1.23e+7 in regular decimal = 12300000.0
            str_num = number + zeros + '.0'
        # Eg: for this condition = 1.23e+1
        if e_power < len(number_mantissa):
            # In this case, we only need to shift the decimal e_power digits to the right
            # So we just copy the digits from mantissa to characteristic and then remove
            # them from mantissa.
            for i in range(e_power):
                number_characteristic = number_characteristic + number_mantissa[i]
            number_mantissa = number_mantissa[i:]
            # Scientific notation 1.23e+1 in regular decimal = 12.3
            str_num = number_characteristic + '.' + number_mantissa
    # characteristic is number left of decimal point.
    characteristic_part = str_num.split('.')[0]
    # mantissa is number right of decimal point.
    mantissa_part = str_num.split('.')[1]
    # If number is supposed to be rounded to whole number,
    # check first decimal digit. If more than 5, return
    # characteristic + 1 else return characteristic
    if precision == 0:
        if mantissa_part and int(mantissa_part[0]) >= 5:
            return type_num(int(characteristic_part) + 1)
        return type_num(characteristic_part)
    # Get the precision of the given number.
    num_precision = len(mantissa_part)
    # Rounding off is done only if number precision is
    # greater than requested precision
    if num_precision <= precision:
        return num
    # Replace the last '5' with 6 so that rounding off returns desired results
    if str_num[-1] == '5':
        str_num = re.sub('5$', '6', str_num)
    result = round(type_num(str_num), precision)
    # If the number was negative, add negative context back
    if negative_number:
        result = result * -1
    return result
重新导入
def自定义整轮(数值,精度=0):
#获取给定数字的类型
type_num=type(num)
#如果给定的类型不是有效的数字类型,请引发TypeError
如果类型_num不在[int,float,Decimal]中:
raise TypeError(“类型{}未定义_round__方法”。格式(类型_num._名称_))
#如果传递的数字为int,则不进行舍入。
如果类型_num==int:
返回数
#将数字转换为字符串。
str_num=str(num).lower()
#我们将从数字中删除负面上下文,并将其添加到最后
负数=假
如果num<0:
负数=真
str_num=str_num[1:]
#如果数字的格式为1e-12或2e+13,我们必须将其转换为
#以标准十进制表示的字符串。
如果str_num中的“e-”:
#对于1.23e-7,e_功率=7
e_power=int(re.findall('e-[0-9]+',str_num)[0][2:]
#对于1.23e-7,数字=123
number=''.join(str_num.split('e-')[0]。split('.'))
零=“”
#零的数量=e_幂-1=6
对于范围内的i(e_功率-1):
零=零+0
#科学记数法1.23e-7,十进制规则=0.000000123
str_num='0.'+0+number
如果str_num中的“e+”:
#对于1.23e+7,e_功率=7
e_power=int(re.findall('e\+[0-9]+',str_num)[0][2:]
#对于1.23e+7,数字_特性=1
#特征是小数点左边的数字。
数字特征=str_num.split('e+')[0]。split('.')[0]
#对于1.23e+7,数字_尾数=23
#尾数是小数点右边的数字。
数字尾数=str_num.split('e+')[0]。split('.')[1]
#对于1.23e+7,数字=123
数字=数字\特征+数字\尾数
零=“”
#例如:在这种情况下=1.23e+7
如果e_power>=len(数字尾数):
#零的数量=e_幂-尾数长度=5
对于范围内的i(e_幂-len(number_尾数)):
零=零+0
#科学记数法1.23e
import re


def custom_round(num, precision=0):
    # Get the type of given number
    type_num = type(num)
    # If the given type is not a valid number type, raise TypeError
    if type_num not in [int, float, Decimal]:
        raise TypeError("type {} doesn't define __round__ method".format(type_num.__name__))
    # If passed number is int, there is no rounding off.
    if type_num == int:
        return num
    # Convert number to string.
    str_num = str(num).lower()
    # We will remove negative context from the number and add it back in the end
    negative_number = False
    if num < 0:
        negative_number = True
        str_num = str_num[1:]
    # If number is in format 1e-12 or 2e+13, we have to convert it to
    # to a string in standard decimal notation.
    if 'e-' in str_num:
        # For 1.23e-7, e_power = 7
        e_power = int(re.findall('e-[0-9]+', str_num)[0][2:])
        # For 1.23e-7, number = 123
        number = ''.join(str_num.split('e-')[0].split('.'))
        zeros = ''
        # Number of zeros = e_power - 1 = 6
        for i in range(e_power - 1):
            zeros = zeros + '0'
        # Scientific notation 1.23e-7 in regular decimal = 0.000000123
        str_num = '0.' + zeros + number
    if 'e+' in str_num:
        # For 1.23e+7, e_power = 7
        e_power = int(re.findall('e\+[0-9]+', str_num)[0][2:])
        # For 1.23e+7, number_characteristic = 1
        # characteristic is number left of decimal point.
        number_characteristic = str_num.split('e+')[0].split('.')[0]
        # For 1.23e+7, number_mantissa = 23
        # mantissa is number right of decimal point.
        number_mantissa = str_num.split('e+')[0].split('.')[1]
        # For 1.23e+7, number = 123
        number = number_characteristic + number_mantissa
        zeros = ''
        # Eg: for this condition = 1.23e+7
        if e_power >= len(number_mantissa):
            # Number of zeros = e_power - mantissa length = 5
            for i in range(e_power - len(number_mantissa)):
                zeros = zeros + '0'
            # Scientific notation 1.23e+7 in regular decimal = 12300000.0
            str_num = number + zeros + '.0'
        # Eg: for this condition = 1.23e+1
        if e_power < len(number_mantissa):
            # In this case, we only need to shift the decimal e_power digits to the right
            # So we just copy the digits from mantissa to characteristic and then remove
            # them from mantissa.
            for i in range(e_power):
                number_characteristic = number_characteristic + number_mantissa[i]
            number_mantissa = number_mantissa[i:]
            # Scientific notation 1.23e+1 in regular decimal = 12.3
            str_num = number_characteristic + '.' + number_mantissa
    # characteristic is number left of decimal point.
    characteristic_part = str_num.split('.')[0]
    # mantissa is number right of decimal point.
    mantissa_part = str_num.split('.')[1]
    # If number is supposed to be rounded to whole number,
    # check first decimal digit. If more than 5, return
    # characteristic + 1 else return characteristic
    if precision == 0:
        if mantissa_part and int(mantissa_part[0]) >= 5:
            return type_num(int(characteristic_part) + 1)
        return type_num(characteristic_part)
    # Get the precision of the given number.
    num_precision = len(mantissa_part)
    # Rounding off is done only if number precision is
    # greater than requested precision
    if num_precision <= precision:
        return num
    # Replace the last '5' with 6 so that rounding off returns desired results
    if str_num[-1] == '5':
        str_num = re.sub('5$', '6', str_num)
    result = round(type_num(str_num), precision)
    # If the number was negative, add negative context back
    if negative_number:
        result = result * -1
    return result
print(round(61.295, 2))
print(round(1.295, 2))
61.3
1.29
from math import ceil
decimal_count = 2
print(ceil(61.295 * 10 ** decimal_count) / 10 ** decimal_count)
print(ceil(1.295 * 10 ** decimal_count) / 10 ** decimal_count)
61.3
1.3
def hard_round(number, decimal_places=0):
    """
    Function:
    - Rounds a float value to a specified number of decimal places
    - Fixes issues with floating point binary approximation rounding in python
    Requires:
    - `number`:
        - Type: int|float
        - What: The number to round
    Optional:
    - `decimal_places`:
        - Type: int 
        - What: The number of decimal places to round to
        - Default: 0
    Example:
    ```
    hard_round(5.6,1)
    ```
    """
    return int(number*(10**decimal_places)+0.5)/(10**decimal_places)
float_number = 12.234325335563
rounded = round(float_number, 3) # 3 is the number of decimal places to be returned.You can pass any number in place of 3 depending on how many decimal places you want to return.
print(rounded)
12.234