파이썬에서 float를 정수로 변환하는 가장 안전한 방법은 무엇입니까?


216

파이썬의 수학 모듈에는 floor& 와 같은 편리한 함수가 있습니다 ceil. 이 함수는 부동 소수점 숫자를 사용하여 아래 또는 위의 가장 가까운 정수를 반환합니다. 그러나 이러한 함수는 응답을 부동 소수점 숫자로 반환합니다. 예를 들면 다음과 같습니다.

import math
f=math.floor(2.3)

이제 다음을 f반환합니다.

2.0

반올림 오류의 위험을 피하지 않고이 부동 소수점에서 정수를 얻는 가장 안전한 방법은 무엇입니까 (예 : 부동 소수점이 1.99999와 같은 경우) 아니면 다른 함수를 사용해야합니까?


7
math.floor v2.6 에서는 float를 반환 하지만 v3에서는 정수를 반환합니다 . 이 시점 (OP 이후 거의 6 년)에는이 문제가 거의 나타나지 않을 수 있습니다.
sancho.s ReinstateMonicaCellio

그러나 numpy는 여전히 float를 반환하므로 질문이 유효합니다.
Vincenzooo

답변:


178

부동 소수점 숫자로 표현할 수있는 모든 정수는 정확한 표현을 갖습니다. 따라서 int결과에 안전하게 사용할 수 있습니다. 부정확 한 표현은 2의 거듭 제곱이 아닌 분모로 유리수를 나타내려고 할 때만 발생합니다.

이 작품은 결코 사소한 것이 아닙니다! 문제의 숫자의 크기가 충분히 작 으면 int (floor (2.3))가 1 일 때 다른 표현이 가능할 경우 int∘floor = ⌊⋅⌋ 인 IEEE 부동 소수점 표현의 속성입니다.

Wikipedia 에서 인용하자면 ,

절대 값이 2 24 이하인 정수 는 단 정밀도 형식으로 정확하게 표현 될 수 있으며, 절대 값이 2 53 이하인 정수 는 배정 밀도 형식으로 정확하게 표현 될 수 있습니다.


8
조금 더 깊이 들어가면 +1. : 당신은 또한 이유에 대한 간략한 설명에 던질 수 en.wikipedia.org/wiki/Floating_point D :
고든 구스타프손

파이썬 2에서 "int"는 C "int"와 같습니다. Python 3에서는 "int, stackoverflow.com/questions/13795758/… 의 크기에 제한이없는 것 같습니다 ."int "의 의미는 운영 체제 및 기본 하드웨어에 따라 다릅니다 ( en.wikipedia 참조) . 조직 / 위키 / 64 bit_computing # 64 bit_data_models를 . 당신은 C-API로 프로그래밍하는 경우, 파이썬 3 길이를 size_t의 정의는 플랫폼에 무엇에 매우 신중해야합니다. docs.python.org/3 /c-api/long.html
Juan

113

사용 int(your non integer number)하면 못을 박습니다.

print int(2.3) # "2"
print int(math.sqrt(5)) # "2"

4
부정적인 번호에 대한이하지 않습니다 일 : floor라운드 반면 아래로 int라운드 0을 향해
요헨

1
@ jochen 나는 int(-2.3)Python 배포판 Canopy 2.7.6에서 테스트 했으며 -2예상대로 얻었습니다 . 공식 수학 정의에서와 같은 방식으로 정수는 음수 일 수 있습니다.
srodriguex

5
나는 동의 int(-2.3)준다 -2당신이 말하는대로쪽으로 반올림 때문에 0, 이 경우에. 대조적으로, 원래의 질문 math.floor은 항상 내림합니다 : math.floor(-2.3)gives -3.0.
jochen

1
그것은 실제로 문제가되지 않습니다. OP는의 결과에서 정수를 원 하며이 math.floor답변은 부동 소수점을 정수로 변환하는 방법을 보여줍니다. 로부터 플로트 가지고 math.floor파이프를 통해를 int, 문제가 해결 :int(math.floor(2.3))
JMTyler

4
질문을 읽었습니까? 그는 int () 함수를 알고 있지만 2.0 대신 1.9999로 문제가 발생할 수 있는지 묻습니다. 당신의 대답은 전혀 대답에 가깝지 않습니다, 당신은 요점을 놓쳤습니다 ...
Mayou36

48

라운드 기능을 사용할 수 있습니다. 두 번째 매개 변수 (유효 자릿수 #)를 사용하지 않으면 원하는 동작을 얻을 수 있다고 생각합니다.

유휴 출력.

>>> round(2.99999999999)
3
>>> round(2.6)
3
>>> round(2.5)
3
>>> round(2.4)
2

28
round적어도 Python 2.6에서는 float 숫자도 반환합니다.
Philipp

8
Python 3.1.2에서 round는 int를 반환합니다.
robert

2
실제로 Python 3.x에서는 정수 roundfloor정수를 모두 반환합니다. 그래서 나는 그 질문이 파이썬 2.x에 관한 것이라고 생각합니다.
Philipp

4
아마도 int(round(2.65))?
teewuane

1
round(6.5)6을 줍니까? ceil()다른 모든 경우에 소수점 다음에 즉시 5 (또는 9 이상)가있을 때 플로트 인 것 같습니다 . 이 경우 왜 이것이 작동하지 않습니까? 또는 숫자가 6으로 끝나고 소수 바로 다음에 5가있을 때 ...
candh

43

이전 결과 중 두 가지를 결합하면 다음과 같은 결과를 얻을 수 있습니다.

int(round(some_float))

이것은 float를 정수로 상당히 의존적으로 변환합니다.


매우 긴 플로트를 반올림하면 어떻게됩니까? 적어도 예외가 발생합니까?
Agostino

@ 아고스티노 "매우 긴 플로트"란 무엇을 의미합니까?
kralyk

@kralyk 나는 float법선 int이 가질 수있는 것보다 더 큰 숫자를 의미합니다 . Python 2에서 (반올림 후) float만 사용하여 나타낼 수 있는 값이 long있습니까?
Agostino

@kralyk 당신은 라운드 후 의미합니까? 그렇다면 예외를 발생시키기 위해 캐스팅하거나 잘라내는 것입니까?
Agostino

@Agostino 아니요,이 int()함수 는 필요한 것을 기반으로 int또는 하나를 생성 long합니다 ...
kralyk

18

이 작품은 결코 사소한 것이 아닙니다! 문제의 숫자의 크기가 충분히 작 으면 int (floor (2.3))가 1 일 때 다른 표현이 가능할 경우 int∘floor = ⌊⋅⌋ 인 IEEE 부동 소수점 표현의 속성입니다.

이 포스트는 왜 그 범위에서 작동하는지 설명합니다 .

이중으로 아무 문제없이 32 비트 정수를 나타낼 수 있습니다. 이 할 수 있는 반올림 문제 수. 더 정확하게는, double은 2 53-2 53 사이의 모든 정수를 나타낼 수 있습니다 .

간단한 설명 : 더블은 최대 53 개의 이진수를 저장할 수 있습니다. 더 필요한 경우 오른쪽에 숫자가 0으로 채워집니다.

패딩없이 저장할 수있는 가장 큰 숫자는 53 개입니다. 당연히 더 적은 숫자가 필요한 모든 (정수) 숫자를 정확하게 저장할 수 있습니다.

111 (생략) 111 (53 )에 1을 더하면 100 ... 000, (53 개의 0)이됩니다. 우리가 알다시피, 우리는 53 자리를 저장할 수 있습니다.

이곳은 2 53의 유래입니다.


자세한 내용 : IEEE-754 부동 소수점 작동 방식을 고려해야합니다.

  1 bit    11 / 8     52 / 23      # bits double/single precision
[ sign |  exponent | mantissa ]

그런 다음 숫자는 다음과 같이 계산됩니다 (여기서는 관련이없는 특수한 경우 제외).

-1 부호 × 1. 가수 × 2 지수-치우침

여기서, 바이어스 = 2 , 지수 1 - 1 - 즉, 1,023 배, 127 / 단일 정밀도 각각.

2 X 를 곱하면 모든 비트 X 자리가 왼쪽으로 이동 한다는 것을 알면 정수의 소수점에 소수점 오른쪽으로 끝나는 모든 비트가 가수로 0으로 끝나는 것을 쉽게 알 수 있습니다.

0을 제외한 모든 정수는 이진 형식으로 다음과 같습니다.

1x ... x 여기서 x -es는 MSB 오른쪽에있는 비트 (가장 중요한 비트)를 나타냅니다.

우리는 0을 제외했기 때문에 항상 하나 인 MSB가 있을 것 입니다. 이것이 저장되지 않는 이유입니다. 정수를 저장하려면 -1 sign × 1.mantissa × 2 exponent-bias 형식으로 가져와야합니다 .

그것은 MSB가 MSB의 왼쪽으로 갈 때까지 소수점 위로 비트를 이동시키는 것과 같습니다. 소수점 오른쪽의 모든 비트는 가수에 저장됩니다.

이것으로부터 MSB와는 별개로 최대 52 개의 이진수를 저장할 수 있음을 알 수 있습니다.

모든 비트가 명시 적으로 저장되는 가장 높은 숫자는 다음과 같습니다.

111(omitted)111.   that's 53 ones (52 + implicit 1) in the case of doubles.

이를 위해 소수점을 52 자리로 이동하도록 지수를 설정해야합니다. 지수를 1 씩 늘리면 소수점 다음에 왼쪽에있는 숫자를 알 수 없습니다.

111(omitted)111x.

일반적으로 0입니다. 전체 가수를 0으로 설정하면 다음과 같은 숫자가 나타납니다.

100(omitted)00x. = 100(omitted)000.

이것은 1과 53의 0, 52가 저장되고 지수로 인해 1이 추가됩니다.

그것은 나타내는 2 (53) 의 경계 (포지티브 및 네거티브 모두) 그 사이 우리가 정확하게 모든 정수를 나타낼 수 자국. 1을 2 53 에 더하고 싶다면 암시 적 제로 (로 표시 x)를 1 로 설정해야 하지만 불가능합니다.


8

math.floor항상 정수를 반환하므로 int(math.floor(some_float))반올림 오류가 발생하지 않습니다.

그러나 반올림 오류는 이미 math.floor(some_large_float), 또는 부동 소수점에 많은 수를 처음 저장할 때도 발생할 수 있습니다 . 플로트에 저장하면 큰 숫자의 정밀도가 떨어질 수 있습니다.


7
보낸 사람 : docs.python.org/2/library/math.html-math.floor (x)-x의 플로어를 x보다 작거나 같은 가장 큰 정수 값인 float로 반환합니다.
Bill Rosmus

int가 이미 같은 일을 할 때 왜 math.floor를 호출해야합니까?
Alex

1
@ 알렉스 : int그리고 floor물론, 음수에 대해 서로 다른 값을 반환합니다.

8

문자열 부동 소수점을 정수로 변환 해야하는 경우이 방법을 사용할 수 있습니다.

예 : '38.0'to38

이것을 int로 변환하기 위해 float 다음 int로 캐스팅 할 수 있습니다. 부동 문자열 또는 정수 문자열에도 작동합니다.

>>> int(float('38.0'))
38
>>> int(float('38'))
38

참고 : 소수점 이하의 숫자는 제거합니다.

>>> int(float('38.2'))
38

1

변수를 사용하여 실수 / 부동을 정수로 변환하는 또 다른 코드 샘플. "vel"은 실수 / 부동 수이며 다음으로 큰 INTEGER 인 "newvel"로 변환됩니다.

import arcpy.math, os, sys, arcpy.da
.
.
with arcpy.da.SearchCursor(densifybkp,[floseg,vel,Length]) as cursor:
 for row in cursor:
    curvel = float(row[1])
    newvel = int(math.ceil(curvel))

0

'가장 안전한'방법을 요구하고 있으므로 최상위 답변 이외의 다른 답변을 제공하겠습니다.

정밀도를 잃지 않도록하는 쉬운 방법은 값을 변환 한 후 값이 같은지 확인하는 것입니다.

if int(some_value) == some_value:
     some_value = int(some_value)

예를 들어 float가 1.0이면 1.0은 1과 같습니다. 따라서 int 로의 변환이 실행됩니다. float가 1.1이면 int (1.1)은 1, 1.1! = 1과 같습니다. 따라서 값은 float로 유지되므로 정밀도를 잃지 않습니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.