四舍五入到最接近的整数

我一直试图四舍五入长浮点数,如:

32.268907563;
32.268907563;
31.2396694215;
33.6206896552;
...

目前还没有成功。我尝试了math.ceil(x)math.floor(x)(虽然这将四舍五入,这不是我要找的)和round(x)也没有工作(仍然是浮点数)。

我该怎么办呢?

代码:

for i in widthRange:
for j in heightRange:
r, g, b = rgb_im.getpixel((i, j))
h, s, v = colorsys.rgb_to_hsv(r/255.0, g/255.0, b/255.0)
h = h * 360
int(round(h))
print(h)
629138 次浏览

TL;博士:

round(x)

将四舍五入并将其更改为整数。

你没有将round(h)赋值给任何变量。当你调用round(h)时,它返回整数,但不做其他任何事情;你需要改变这一行:

h = round(h)

将新值赋给h


正如@plowman在评论中所说,Python的round()并不像人们通常期望的那样工作,这是因为数字存储为变量的方式通常不是你在屏幕上看到的方式。有答案很多解释这种行为。

避免这个问题的一种方法是使用这个答案声明的Decimal。

为了使这个答案正常工作而不使用额外的库,使用自定义舍入函数会很方便。我提出了以下解决方案,据我测试,避免了所有存储问题。它基于使用字符串表示,通过repr()(不是str()!)获得。这看起来很俗气,但这是我找到的解决所有案件的唯一方法。它同时适用于Python2和Python3。

def proper_round(num, dec=0):
num = str(num)[:str(num).index('.')+dec+2]
if num[-1]>='5':
return float(num[:-2-(not dec)]+str(int(num[-2-(not dec)])+1))
return float(num[:-1])

测试:

>>> print(proper_round(1.0005,3))
1.001
>>> print(proper_round(2.0005,3))
2.001
>>> print(proper_round(3.0005,3))
3.001
>>> print(proper_round(4.0005,3))
4.001
>>> print(proper_round(5.0005,3))
5.001
>>> print(proper_round(1.005,2))
1.01
>>> print(proper_round(2.005,2))
2.01
>>> print(proper_round(3.005,2))
3.01
>>> print(proper_round(4.005,2))
4.01
>>> print(proper_round(5.005,2))
5.01
>>> print(proper_round(1.05,1))
1.1
>>> print(proper_round(2.05,1))
2.1
>>> print(proper_round(3.05,1))
3.1
>>> print(proper_round(4.05,1))
4.1
>>> print(proper_round(5.05,1))
5.1
>>> print(proper_round(1.5))
2.0
>>> print(proper_round(2.5))
3.0
>>> print(proper_round(3.5))
4.0
>>> print(proper_round(4.5))
5.0
>>> print(proper_round(5.5))
6.0
>>>
>>> print(proper_round(1.000499999999,3))
1.0
>>> print(proper_round(2.000499999999,3))
2.0
>>> print(proper_round(3.000499999999,3))
3.0
>>> print(proper_round(4.000499999999,3))
4.0
>>> print(proper_round(5.000499999999,3))
5.0
>>> print(proper_round(1.00499999999,2))
1.0
>>> print(proper_round(2.00499999999,2))
2.0
>>> print(proper_round(3.00499999999,2))
3.0
>>> print(proper_round(4.00499999999,2))
4.0
>>> print(proper_round(5.00499999999,2))
5.0
>>> print(proper_round(1.0499999999,1))
1.0
>>> print(proper_round(2.0499999999,1))
2.0
>>> print(proper_round(3.0499999999,1))
3.0
>>> print(proper_round(4.0499999999,1))
4.0
>>> print(proper_round(5.0499999999,1))
5.0
>>> print(proper_round(1.499999999))
1.0
>>> print(proper_round(2.499999999))
2.0
>>> print(proper_round(3.499999999))
3.0
>>> print(proper_round(4.499999999))
4.0
>>> print(proper_round(5.499999999))
5.0

最后,正确的答案是:

# Having proper_round defined as previously stated
h = int(proper_round(h))

测试:

>>> proper_round(6.39764125, 2)
6.31 # should be 6.4
>>> proper_round(6.9764125, 1)
6.1  # should be 7

这里的问题是,第__abc0位小数可以是9,如果第__abc1位数字>=5,则9将变成0,并且1应该进位到第__abc2位数字。

如果我们考虑到这一点,我们得到:

def proper_round(num, dec=0):
num = str(num)[:str(num).index('.')+dec+2]
if num[-1]>='5':
a = num[:-2-(not dec)]       # integer part
b = int(num[-2-(not dec)])+1 # decimal part
return float(a)+b**(-dec+1) if a and b == 10 else float(a+str(b))
return float(num[:-1])

在上面描述的情况中,b = 10和以前的版本只会连接ab,这将导致10的连接,其中后面的0将消失。这个版本将b转换为基于dec的右小数点后数位,作为一个适当的进位。

使用round(x, y)。它会把你的数字四舍五入到你想要的小数点后的位置。

例如:

>>> round(32.268907563, 3)
32.269

round(value,significantDigit)是普通的解决方案,然而,当整数值以5结尾时,从数学角度来看,这并不像人们所期望的那样。如果5位于被舍入的数字后面,则这些值有时只会按预期四舍五入(即8.005舍入到两位十进制数字会得到8.01)。由于浮点数学的特殊性,对于某些值,它们将被四舍五入!

即。

>>> round(1.0005,3)
1.0
>>> round(2.0005,3)
2.001
>>> round(3.0005,3)
3.001
>>> round(4.0005,3)
4.0
>>> round(1.005,2)
1.0
>>> round(5.005,2)
5.0
>>> round(6.005,2)
6.0
>>> round(7.005,2)
7.0
>>> round(3.005,2)
3.0
>>> round(8.005,2)
8.01

奇怪。

假设你的目的是对科学统计进行传统的舍入,这是一个方便的包装器,可以让round函数按预期工作,需要Decimal等额外的东西。

>>> round(0.075,2)


0.07


>>> round(0.075+10**(-2*5),2)


0.08

啊哈!基于这个我们可以做一个函数。

def roundTraditional(val,digits):
return round(val+10**(-len(str(val))-1), digits)

基本上,这将添加一个值,该值保证小于你试图在其上使用round的字符串的最小给定数字。通过添加这个小量,它在大多数情况下保留了round的行为,同时确保如果比被舍入的数字小的数字是5,它就四舍五入,如果是4,它就四舍五入。

使用10**(-len(val)-1)的方法是经过深思熟虑的,因为它是你可以添加来强制移位的最大的小数字,同时也确保你添加的值不会改变四舍五入,即使小数点.缺失。我可以只使用10**(-len(val))和条件if (val>1)来减去1…但更简单的方法是总是减去1,因为这不会太大改变这个解决方法可以正确处理的十进制数字的适用范围。如果您的值达到类型的限制,这种方法将失败,但对于几乎所有有效的十进制值范围,它应该可以工作。

你也可以使用小数库来实现这一点,但我建议的包装器更简单,在某些情况下可能是首选。


感谢Blckknght指出5边缘情况只发生在某些值。此外,这个答案的早期版本还不够明确,以至于奇怪的舍入行为仅当紧接于要舍入的数字的数字具有5时才发生

Python不就是在做半圆到偶数吗,就像IEEE 754规定的那样?

小心重新定义,或使用“非标准”舍入…

(另见https://stackoverflow.com/a/33019948/109839)

对于积极的方面,试试

int(x + 0.5)

为了让它也适用于底片,试试吧

int(x + (0.5 if x > 0 else -0.5))

int()的工作原理类似于一个楼层函数,因此你可以利用这个属性。这绝对是最快的方法。

如果你需要(例如)a的两位近似值,那么

. int(A*100+0.5)/100.0将做你正在寻找的

如果你需要三位数的近似值,可以乘以1000再除以1000等等。

如果使用python3,也可以使用numpy。X是一个例子

import numpy as np
x = 2.3
print(np.rint(x))
>>> 2.0

为了这个目的,我建议你做下面的事情

int(round(x))

这将给出最接近的整数。

希望这能有所帮助!!

您的解决方案是调用舍入而不指定第二个参数(小数点后位数)

>>> round(0.44)
0
>>> round(0.64)
1

哪个结果比

>>> int(round(0.44, 2))
0
>>> int(round(0.64, 2))
0

来自Python文档https://docs.python.org/3/library/functions.html#round

轮([,ndigits])

返回小数点后精确到ndigits的数字。如果 ndigits被省略或为None,它返回与其最近的整数 输入。< / p >

请注意

round()对于浮点数的行为可能会令人惊讶:例如, 轮(2.675,2)给出2.67而不是预期的2.68。这不是 错误:这是一个事实的结果,大多数十进制分数不能 精确地表示为浮点数。参见浮点运算:问题

.

.

我使用并建议以下解决方案(python3.6):

y = int(x + (x % (1 if x >= 0 else -1)))

它适用于半数(正数和负数),甚至比int(round(x))更快:

round_methods = [lambda x: int(round(x)),
lambda x: int(x + (x % (1 if x >= 0 else -1))),
lambda x: np.rint(x).astype(int),
lambda x: int(proper_round(x))]


for rm in round_methods:
%timeit rm(112.5)
Out:
201 ns ± 3.96 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
159 ns ± 0.646 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
925 ns ± 7.66 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
1.18 µs ± 8.66 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)


for rm in round_methods:
print(rm(112.4), rm(112.5), rm(112.6))
print(rm(-12.4), rm(-12.5), rm(-12.6))
print('=' * 11)


Out:
112 112 113
-12 -12 -13
===========
112 113 113
-12 -13 -13
===========
112 112 113
-12 -12 -13
===========
112 113 113
-12 -13 -13
===========

像这样的东西应该也能工作

import numpy as np


def proper_round(a):
'''
given any real number 'a' returns an integer closest to 'a'
'''
a_ceil = np.ceil(a)
a_floor = np.floor(a)
if np.abs(a_ceil - a) < np.abs(a_floor - a):
return int(a_ceil)
else:
return int(a_floor)

说实话,这一点很棘手。不过,有许多简单的方法可以做到这一点。使用math.ceil()round()math.floor(),你可以通过使用例如:
来获得integer

n = int(round(n))

如果在使用n = 5.23函数之前,将返回5。如果你想四舍五入到不同的位值,你可以使用这个函数:

def Round(n,k):
point = '%0.' + str(k) + 'f'
if k == 0:
return int(point % n)
else:
return float(point % n)

如果我们再次使用n (5.23),四舍五入到最接近的十分之一,并将答案打印到控制台,我们的代码将是:

Round(5.23,1)

返回5.2。最后,如果你想四舍五入到最接近的值,比如,1.2,你可以使用下面的代码:

def Round(n,k):
return k * round(n/k)

如果我们想要将n四舍五入为1.2,我们的代码将是:

print(Round(n,1.2))

我们的结果是:

4.8

谢谢你!如果您有任何问题,请添加评论。(节日快乐!)

点击链接查看解释。在我的帖子中链接的文章讨论了所有的代码以及如何使用它。

https://kodify.net/python/math/truncate-decimals/

import math


def truncate(number, decimals=0):
"""
Returns a value truncated to a specific number of decimal places.
"""
if not isinstance(decimals, int):
raise TypeError("decimal places must be an integer.")
elif decimals < 0:
raise ValueError("decimal places has to be 0 or more.")
elif decimals == 0:
return math.trunc(number)


factor = 10.0 ** decimals
return math.trunc(number * factor) / factor

对x500进行舍入的基本原理是……到x位中的偶数值是正确的方法,与值的二进制表示无关。这是一种“合适的”算法。高级科学课和统计学课都教这个。但为什么会这样呢?

最小化累积错误!

当您舍入一个值时,您在该项上引入了一个错误值。如果你把大量的值加在一起,你总是四舍五入到x500…当你的值上升[即x+1]时,你的误差累积就会有一个固有的偏差。

在N个数字的集合上,其中M个数字的形式是x500…,四舍五入方法将引入一个M * 0.5的+ve误差项。

然而,如果你总是四舍五入为偶数,那么你会得到一个期望,这M个错误项中有一半是+ve,一半是-ve。因此,你有expecatation,他们将取消给你留下一个净零误差从这M项。0的误差不是比M * 0.5的误差好多了吗?

但是,这个净0错误只是一个期望。当你考虑在“fair”中翻转;硬币(一个类似的问题)这样"头"= +1和"尾"= -1, M次,并将所有投掷的总和相加,有一个统计上的0结果的期望,但“漫游”的大小;从0开始(可以是+ve或-ve)通常被根号M限制——还是log(M)?好久没翻开统计书了。实际的答案(根号或对数)与这个问题无关,因为根号(M)和对数(M)对于所有的M>都小于M;1]。

因此,由于它属于我们的数字和场景,M值的形式为x500…,由于M是有限的,我们有一个期望,这些M值的误差项将为零,但我们还有一个更强的期望,误差项的大小应该由你要四舍五入的数字的根号(M) * 0.5约束。

0是很棒的,但是预期根号(M) * 0.5仍然比保证 M * 0.5好得多。

是的,你可以有一个病态的情况,你最终得到M * 0.5,但这样的情况应该是一个异常值,而不是常态——这个罕见的异常值并不比“总是四舍五入”更糟糕。的方法。

在正确答案中提到的这是不工作的,如果我使用79.5。它给出的答案是710,不是80。

def proper_round(num, dec=0):
num= int(num*pow(10,dec+1))
lastDigit = (str(num))[-1]
num = int(num/10)
if lastDigit >='5':
num+=1
return float(num/pow(10,dec))

上述代码得到了较好的结果

要四舍五入到最接近的int数,使用numpy:

p=np.array([     430.15,      57.868,      70.697,      198.13])
p=np.round(p)

p:

array([        430,          58,          71,         198])