파이썬에서 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 형식으로 가져와야합니다 .
That's saying the same as shifting the bits over the decimal point until there's only the MSB towards the left of the MSB. All the bits right of the decimal point are then stored in the mantissa.
From this, we can see that we can store at most 52 binary digits apart from the MSB.
It follows that the highest number where all bits are explicitly stored is
111(omitted)111. that's 53 ones (52 + implicit 1) in the case of doubles.
For this, we need to set the exponent, such that the decimal point will be shifted 52 places. If we were to increase the exponent by one, we cannot know the digit right to the left after the decimal point.
111(omitted)111x.
By convention, it's 0. Setting the entire mantissa to zero, we receive the following number:
100(omitted)00x. = 100(omitted)000.
That's a 1 followed by 53 zeroes, 52 stored and 1 added due to the exponent.
It represents 253, which marks the boundary (both negative and positive) between which we can accurately represent all integers. If we wanted to add one to 253, we would have to set the implicit zero (denoted by the x
) to one, but that's impossible.
math.floor
will always return an integer number and thus int(math.floor(some_float))
will never introduce rounding errors.
The rounding error might already be introduced in math.floor(some_large_float)
, though, or even when storing a large number in a float in the first place. (Large numbers may lose precision when stored in floats.)
If you need to convert a string float to an int you can use this method.
Example: '38.0'
to 38
In order to convert this to an int you can cast it as a float then an int. This will also work for float strings or integer strings.
>>> int(float('38.0'))
38
>>> int(float('38'))
38
Note: This will strip any numbers after the decimal.
>>> int(float('38.2'))
38
Another code sample to convert a real/float to an integer using variables. "vel" is a real/float number and converted to the next highest 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))
Since you're asking for the 'safest' way, I'll provide another answer other than the top answer.
An easy way to make sure you don't lose any precision is to check if the values would be equal after you convert them.
if int(some_value) == some_value:
some_value = int(some_value)
If the float is 1.0 for example, 1.0 is equal to 1. So the conversion to int will execute. And if the float is 1.1, int(1.1) equates to 1, and 1.1 != 1. So the value will remain a float and you won't lose any precision.
df['Column_Name']=df['Column_Name'].astype(int)
참고URL : https://stackoverflow.com/questions/3387655/safest-way-to-convert-float-to-integer-in-python
'Programing' 카테고리의 다른 글
PHP가 null이거나 비어 있습니까? (0) | 2020.05.17 |
---|---|
“기능”과“절차”의 차이점은 무엇입니까? (0) | 2020.05.16 |
Windows에서 파일의 대소 문자를 변경 하시겠습니까? (0) | 2020.05.16 |
MySQL의 열에서 동일한 값을 가진 행 찾기 (0) | 2020.05.16 |
Scala에서 Vector를 언제 선택해야합니까? (0) | 2020.05.16 |