가장 가까운 정수로 반올림
나는 다음과 같이 긴 부동 소수점 숫자를 반올림하려고했습니다.
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)
int(round(x))
반올림하고 정수로 변경합니다
편집하다:
변수에 int (round (h))를 할당하지 않았습니다. int (round (h))를 호출하면 정수를 반환하지만 다른 작업은 수행하지 않습니다. 그 줄을 다음과 같이 변경해야합니다.
h = int(round(h))
h에 새 값을 할당하려면
편집 2 :
의견에서 @plowman이 말했듯이 Python round()
은 정상적으로 예상대로 작동하지 않으며 숫자가 변수로 저장되는 방식은 일반적으로 화면에서 보는 방식이 아니기 때문입니다. 이 동작을 설명하는 많은 답변이 있습니다.
파이썬에서 round ()가 올바르게 반올림되지 않는 것 같습니다.
이 문제를 피하는 한 가지 방법은이 답변에서 언급 한 십진수를 사용하는 것입니다 : https://stackoverflow.com/a/15398691/4345659
추가 라이브러리를 사용하지 않고이 답변이 제대로 작동하려면 사용자 정의 반올림 기능을 사용하는 것이 편리합니다. 많은 수정을 한 후 테스트 한 모든 저장 문제를 피할 수있는 다음 솔루션을 생각해 냈습니다. repr()
(NOT 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))
편집 3 :
테스트 :
>>> proper_round(6.39764125, 2)
6.31 # should be 6.4
>>> proper_round(6.9764125, 1)
6.1 # should be 7
The gotcha here is that the dec
-th decimal can be 9 and if the dec+1
-th digit >=5 the 9 will become a 0 and a 1 should be carried to the dec-1
-th digit.
If we take this into consideration, we get:
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])
In the situation described above b = 10
and the previous version would just concatenate a
and b
which would result in a concatenation of 10
where the trailing 0 would disappear. This version transforms b
to the right decimal place based on dec
, as a proper carry.
Use round(x, y)
. It will round up your number up to your desired decimal place.
For example:
>>> round(32.268907563, 3)
32.269
round(value,significantDigit)
is the ordinary solution, however this does not operate as one would expect from a math perspective when round values ending in 5
. If the 5
is in the digit just after the one you're rounded to, these values are only sometimes rounded up as expected (i.e. 8.005
rounding to two decimal digits gives 8.01
). For certain values due to the quirks of floating point math, they are rounded down instead!
i.e.
>>> 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
Weird.
Assuming your intent is to do the traditional rounding for statistics in the sciences, this is a handy wrapper to get the round
function working as expected needing to import
extra stuff like Decimal
.
>>> round(0.075,2)
0.07
>>> round(0.075+10**(-2*5),2)
0.08
Aha! So based on this we can make a function...
def roundTraditional(val,digits):
return round(val+10**(-len(str(val))-1), digits)
Basically this adds a value guaranteed to be smaller than the least given digit of the string you're trying to use round
on. By adding that small quantity it preserve's round
's behavior in most cases, while now ensuring if the digit inferior to the one being rounded to is 5
it rounds up, and if it is 4
it rounds down.
The approach of using 10**(-len(val)-1)
was deliberate, as it the largest small number you can add to force the shift, while also ensuring that the value you add never changes the rounding even if the decimal .
is missing. I could use just 10**(-len(val))
with a condiditional if (val>1)
to subtract 1
more... but it's simpler to just always subtract the 1
as that won't change much the applicable range of decimal numbers this workaround can properly handle. This approach will fail if your values reaches the limits of the type, this will fail, but for nearly the entire range of valid decimal values it should work.
You can also use the decimal library to accomplish this, but the wrapper I propose is simpler and may be preferred in some cases.
Edit: Thanks Blckknght for pointing out that the 5
fringe case occurs only for certain values. Also an earlier version of this answer wasn't explicit enough that the odd rounding behavior occurs only when the digit immediately inferior to the digit you're rounding to has a 5
.
For positives, try
int(x + 0.5)
To make it work for negatives too, try
int(x + (0.5 if x > 0 else -0.5))
int()
works like a floor function and hence you can exploit this property. This is definitely the fastest way.
Isn't just Python doing round half to even, as prescribed by IEEE 754?
Be careful redefining, or using "non-standard" rounding…
(See also https://stackoverflow.com/a/33019948/109839)
You can also use numpy assuming if you are using python3.x here is an example
import numpy as np
x = 2.3
print(np.rint(x))
>>> 2.0
Your solution is calling round without specifying the second argument (number of decimal places)
>>> round(0.44)
0
>>> round(0.64)
1
which is a much better result than
>>> int(round(0.44, 2))
0
>>> int(round(0.64, 2))
0
From the Python documentation at https://docs.python.org/3/library/functions.html#round
round(number[, ndigits])
Return number rounded to ndigits precision after the decimal point. If ndigits is omitted or is None, it returns the nearest integer to its input.
Note
The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float. See Floating Point Arithmetic: Issues and Limitations for more information.
If you need (for example) a two digit approximation for A, then int(A*100+0.5)/100.0
will do what you are looking for.
If you need three digit approximation multiply and divide by 1000 and so on.
For this purpose I would suggest just do the following thing -
int(round(x))
This will give you nearest integer.
Hope this helps!!
I use and may advise the following solution (python3.6):
y = int(x + (x % (1 if x >= 0 else -1)))
It works fine for half-numbers (positives and negatives) and works even faster than 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
===========
참고URL : https://stackoverflow.com/questions/31818050/round-number-to-nearest-integer
'Programing' 카테고리의 다른 글
삭제와 삭제의 차이점 (0) | 2020.05.15 |
---|---|
python / numpy를 사용하여 백분위 수를 어떻게 계산합니까? (0) | 2020.05.15 |
반복하는 동안 컬렉션에서 요소 제거 (0) | 2020.05.15 |
파일의 시작 부분에 텍스트를 삽입하는 방법? (0) | 2020.05.15 |
Virtualenvs의 깨진 참조 (0) | 2020.05.15 |