如何围绕浮点数的一半 Python?

我遇到了这个功能的奇怪行为
round//

:


for i in range/1, 15, 2/:
n = i / 2
print/n, "=>", round/n//


此代码打印:


0.5 => 0
1.5 => 2
2.5 => 2
3.5 => 4
4.5 => 4
5.5 => 6
6.5 => 6


我预期的浮动价值将永远以大的方式舍入,而是它们被围绕到最近的偶数。

为什么这种行为,以及获得正确结果的最佳方式是什么?

我试着用
https://docs.python.org/3.5/library/fractions.html
, 但结果是一样的。
已邀请:

石油百科

赞同来自:

https://docs.python.org/3/libr ... mplex
它清楚地编写了这种行为:


round/x[, n]/


x

之前四舍五入 n 数字,四舍五入甚至。 如果一个 n 省略,然后默认为相等 0.

注意

四舍五入甚至

. 它也被称为

舍入银行家

; 而不是始终围绕或向下舍入 /加重舍入错误/, 县到最近的

甚至

数字,你平均舍入错误。

如果您需要更多地控制舍入行为 , 使用
https://docs.python.org/3/library/decimal.html
decimal

, 这允许您准确表明什么
https://docs.python.org/3/libr ... modes
.

例如,从一半开始:


>>> from decimal import localcontext, Decimal, ROUND_HALF_UP
>>> with localcontext// as ctx:
... ctx.rounding = ROUND_HALF_UP
... for i in range/1, 15, 2/:
... n = Decimal/i/ / 2
... print/n, '=>', n.to_integral_value///
...
0.5 => 1
1.5 => 2
2.5 => 3
3.5 => 4
4.5 => 5
5.5 => 6
6.5 => 7

石油百科

赞同来自:

例如:


from decimal import Decimal, ROUND_HALF_UP

Decimal/1.5/.quantize/0, ROUND_HALF_UP/

# This also works for rounding to the integer part:
Decimal/1.5/.to_integral_value/rounding=ROUND_HALF_UP/

冰洋

赞同来自:

您可以使用它:


import math
def normal_round/n/:
if n - math.floor/n/ < 0.5:
return math.floor/n/
return math.ceil/n/


它将正确地向上或向下绕数。

快网

赞同来自:

round//

取决于数字是偶数还是奇数,它将被向上或向下舍入。 简单的方式只绕它:


int/num + 0.5/


如果您希望它正常工作以进行负数,请使用:


//num > 0/ - /num < 0// * int/abs/num/ + 0.5/


请注意,它可以破坏大数字或真正准确的数字,如
5000000000000001.0


0.49999999999999994

.

风见雨下

赞同来自:

您看到的行为是典型的舍入行为 IEEE 754. 如果他必须在与入口不同的两个数字之间进行选择,甚至总是选择。 这种行为的优点是平均舍入效果为零 - 同样的数量上下圆形。 如果您在顺序方向上的中途偏转,则舍入会影响预期值。

如果目标是一个公平的舍入,你看到的行为是对的,但它并不总是你需要的。

获得所需的舍入类型的一个技巧 - 这是添加的 0.5, 然后拿这个词。 例如,添加 0.5 到 2.5 给 3, 与地板 3.

郭文康

赞同来自:

我喜欢答案 fedor2612. 我用一个可选的论点扩展了它 "decimals" 对于那些想要使用此功能来舍入任意数量的十进制符号的人 /让我们说,例如,如果你想环绕货币 $26.455 到 $26.46/.


import math

def normal_round/n, decimals=0/:
expoN = n * 10 ** decimals
if abs/expoN/ - abs/math.floor/expoN// < 0.5:
return math.floor/expoN/ / 10 ** decimals
return math.ceil/expoN/ / 10 ** decimals

oldRounding = round/26.455,2/
newRounding = normal_round/26.455,2/

print/oldRounding/
print/newRounding/


出口:

26.45

26.46

帅驴

赞同来自:

简短版本:使用
https://docs.python.org/3/library/decimal.html
. 它可以准确代表类型的类型 2.675, 不像 Python 浮子,在那里 2.675

真的

2.67499999999999982236431605997495353221893310546875 /确切地/. 您可以指定所需的舍入: ROUND_CEILING, ROUND_DOWN, ROUND_FLOOR, ROUND_HALF_DOWN, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_UP 和round_05up-所有这些选项。

快网

赞同来自:

舍入到最近的偶数是数值学科的通常做法。 "Rounding up" 导致对大结果的轻微流离失所。

所以,从科学建立的角度来看,
round

它有适当的行为。

八刀丁二

赞同来自:

在这件事中,这主要是在将正整数划分时的问题 2. 最简单的方法 -
int/n + 0.5/

对于个人数字。

但是,我们无法将其应用于排名,因此我们可以做些什么,例如, A pandas dataframe, 而不进入周期,是:


import numpy as np
df['rounded_division'] = np.where/df['some_integer'] % 2 == 0, round/df['some_integer']/2,0/, round//df['some_integer']+1//2,0//

君笑尘

赞同来自:

这是另一种解决方案。
它将作为普通的圆形工作 excel.


from decimal import Decimal, getcontext, ROUND_HALF_UP

round_context = getcontext//
round_context.rounding = ROUND_HALF_UP

def c_round/x, digits, precision=5/:
tmp = round/Decimal/x/, precision/
return float/tmp.__round__/digits//



c_round/0.15, 1/ -> 0.2, c_round/0.5, 0/ -> 1

郭文康

赞同来自:

您可以使用:


from decimal import Decimal, ROUND_HALF_UP

for i in range/1, 15, 2/:
n = i / 2
print/n, "=>", Decimal/str/n//.quantize/Decimal/"1"/, rounding=ROUND_HALF_UP//

奔跑吧少年

赞同来自:

没有任何库的经典数学舍入


def rd/x,y=0/:
''' A classical mathematical rounding by Voznica '''
m = int/'1'+'0'*y/ # multiplier - how many positions to the right
q = x*m # shift to the right by multiplier
c = int/q/ # new number
i = int/ /q-c/*10 / # indicator number on the right
if i >= 5:
c += 1
return c/m

Compare:

print/ round/0.49/, round/0.51/, round/0.5/, round/1.5/, round/2.5/, round/0.15,1// # 0 1 0 2 2 0.1

print/ rd/0.49/, rd/0.51/, rd/0.5/, rd/1.5/, rd/2.5/, rd/0.15,1// # 0 1 1 2 3 0.2

奔跑吧少年

赞同来自:

达到了以下决定 "school fashion rounding" 不使用模块
decimal

/这结果很慢/.


def school_round/a_in,n_in/:
''' python uses "banking round; while this round 0.05 up" '''
if /a_in * 10 ** /n_in + 1// % 10 == 5:
return round/a_in + 1 / 10 ** /n_in + 1/, n_in/
else:
return round/a_in, n_in/


例如。


print/round/0.005,2// # 0
print/school_round/0.005,2// #0.01

江南孤鹜

赞同来自:

知识
round/9.99,0/

roundov t.
int=10


int/9.99/

roundov t.
int=9

成功带来:

目的:提供更小且更大的圆形号码取决于
value



def get_half_round_numers/self, value/:
"""
Returns dict with upper_half_rn and lower_half_rn
:param value:
:return:
"""
hrns = {}
if not isinstance/value, float/:
print/"Error>Input is not a float. None return."/
return None

value = round/value,2/
whole = int/value/ # Rounds 9.99 to 9
remainder = /value - whole/ * 100

if remainder >= 51:
hrns['upper_half_rn'] = round/round/value,0/,2/ # Rounds 9.99 to 10
hrns['lower_half_rn'] = round/round/value,0/ - 0.5,2/
else:
hrns['lower_half_rn'] = round/int/value/,2/
hrns['upper_half_rn'] = round/int/value/ + 0.5,2/

return hrns


一些试验:

https://i.stack.imgur.com/CTTxY.png
m

三叔

赞同来自:

import math
# round tossing n digits from the end
def my_round/n, toss=1/:

def normal_round/n/:
if isinstance/n, int/:
return n
intn, dec = str/n/.split/"."/
if int/dec[-1]/ >= 5:
if len/dec/ == 1:
return math.ceil/n/
else:
return float/intn + "." + str/int/dec[:-1]/ + 1//
else:
return float/intn + "." + dec[:-1]/

while toss >= 1:
n = normal_round/n/
toss -= 1
return n


for n in [1.25, 7.3576, 30.56]:
print/my_round/n, 2//

1.0
7.36
31

知食

赞同来自:

你可以尝试一下


def round/num/:
return round/num + 10**/-9//


它会起作用,因为
num = x.5

总是会
x.5 + 0.00...01

在更近的过程中
x+1

, 因此,功能 round 将正常工作,她将会回合
x.5


x+1

要回复问题请先登录注册