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

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

import math
f=math.floor(2.3)

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

2.0

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



답변

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

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

Wikipedia 에서 인용하자면 ,

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


답변

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

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


답변

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

유휴 출력.

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


답변

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

int(round(some_float))

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


답변

이 작품은 결코 사소한 것이 아닙니다! 문제의 숫자의 크기가 충분히 작 으면 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 로 설정해야 하지만 불가능합니다.


답변

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

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


답변

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

예 : '38.0'to38

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

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

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

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