programing

Python의 math.ceil() 및 math.floor() 연산이 정수 대신 floor()를 반환하는 이유는 무엇입니까?

magicmemo 2023. 6. 10. 08:43
반응형

Python의 math.ceil() 및 math.floor() 연산이 정수 대신 floor()를 반환하는 이유는 무엇입니까?

누가 이것을 설명할 수 있습니까(문서 강조 마이닝에서 직접):

math.ceil(x) x의 천장을 x보다 크거나 같은 가장 작은 정수 값인 플로트반환합니다.

math.floor(x) x의 바닥을 x보다 작거나 같은 가장 큰 정수 값인 플로어반환합니다.

왜?.ceil그리고..floor정의상 정수를 계산해야 하는 리턴 플로트는 무엇입니까?


편집:

음, 이것은 그들이 플로트를 반환해야 하는지에 대해 매우 좋은 논쟁을 일으켰고, 저는 막 그 아이디어에 익숙해지고 있었는데, @jcollado가 그들이 실제로 Python 3에서 int를 반환한다고 지적했습니다.

다른 답변에서 지적했듯이, 파이썬에서 그들은 아마도 오버플로 문제를 방지하기 위한 과거의 이유 때문에 플로트를 반환합니다.그러나 python 3에서는 정수를 반환합니다.

>>> import math
>>> type(math.floor(3.1))
<class 'int'>
>>> type(math.ceil(3.1))
<class 'int'>

자세한 내용은 PEP 3141에서 확인할 수 있습니다.

부동 소수점 숫자의 범위는 일반적으로 정수 범위를 초과합니다.부동 소수점 값을 반환함으로써 함수는 표현 가능한 정수 범위 밖에 있는 입력 값에 대해 감지 가능한 값을 반환할 수 있습니다.

고려 사항:한다면floor()했습니다. 's 정습반니다했환수를다▁should▁an,▁returned▁integer. 무엇을 반환해야 합니까?floor(1.0e30)답례?

파이썬의 정수는 이제 임의의 정밀도이지만 항상 이런 식은 아니었습니다.표준 라이브러리 함수는 동등한 C 라이브러리 함수 주위의 얇은 래퍼입니다.

왜냐하면 파이썬의 수학 라이브러리는 플로트를 반환하는 C 수학 라이브러리 주변의 얇은 래퍼이기 때문입니다.

당신의 혼란의 원인은 당신의 논평에서 분명합니다.

천장/바닥 작업의 전체 포인트는 플로트를 정수로 변환하는 것입니다!

천장 및 바닥 작업의 요점은 부동 소수점 데이터를 정수 값으로 반올림하는 것입니다.형식 변환을 수행하지 않습니다.정수 값을 가져와야 하는 사용자는 작업 후에 명시적으로 변환할 수 있습니다.

정수를 반환하는 천장 또는 플로트 작업만 사용할 수 있는 경우 반올림하여 정수 값을 구현할 수 없습니다.먼저 입력이 표시 가능한 정수 범위 내에 있는지 확인한 다음 함수를 호출해야 합니다. 별도의 코드 경로에서 NaN과 무한대를 처리해야 합니다.

또한 IEEE 754를 준수하려면 부동 소수점 번호를 반환하는 천장 및 바닥 버전이 있어야 합니다.

Python 2.4 이전 버전에서는 정수가 잘린 실수의 전체 범위를 수용할 수 없었습니다.

http://docs.python.org/whatsnew/2.4.html#pep-237-unifying-long-integers-and-integers

플로트의 범위가 정수의 범위보다 크기 때문에 정수를 반환하면 오버플로가 발생할 수 있습니다.

이것은 매우 흥미로운 질문입니다!하므로 (플로트는지수저는데필로므요하비가트하장를=(▁as▁to로므▁the필▁bits▁a▁float하▁requires▁some요ent▁(▁expon플▁storebits_for_exponent보다 큰 의 부동 수2**(float_size - bits_for_exponent)항상 정수 값이 됩니다!다른 극단에서 음수 지수를 가진 부동소수점은 다음 중 하나를 제공합니다.1,0또는-1이 함수는 숫자가 정수 유형의 범위를 벗어날 때마다 원래 숫자를 반환하기 때문에 정수 범위 대 부동 범위에 대한 논의가 진행됩니다.python 함수는 의 래퍼입니다.C기능 그리고 그래서 이것은 정말로 결함입니다.C를 반환하고 에게 범위범위를 로 지정해야 했습니다.NaN/Inf천장/층을 부르기 전에 확인합니다.

따라서 논리적인 답변은 이러한 함수가 유용할 때만 정수 범위 내의 값을 반환하므로 플로트를 반환한다는 사실은 실수이며 이를 실현하는 데 매우 현명합니다!

아마도 다른 언어들도 그렇게 하기 때문에 일반적으로 받아들여지는 행동일 것입니다. (다른 답변에 나와 있는 것처럼, 좋은 이유로)

이것은 최근에 저를 완전히 당황하게 했습니다.왜냐하면 1970년대부터 C에서 프로그래밍을 해왔고 이제서야 파이썬의 세부 사항을 배우기 때문입니다.math.floor()의 이 이상한 행동처럼.

파이썬의 수학 라이브러리는 C 표준 수학 라이브러리에 액세스하는 방법입니다.그리고 C 표준 수학 라이브러리는 sin(), cos(), sqrt()와 같은 부동소수점 수치 함수의 모음입니다.수치 계산의 맥락에서 플로어() 함수는 항상 플로트를 반환했습니다.지금까지 50년 동안.이것은 수치 계산 표준의 일부입니다.C의 수학 라이브러리에 익숙한 사람들에게, 우리는 그것을 단지 "수학 함수"로만 이해하지 못합니다.우리는 그것이 부동소수점 알고리즘의 집합이라고 이해합니다.NFPAL - 숫자 부동 소수점 알고리즘 라이브러리와 같은 이름이 더 나을 것입니다.:)

우리 중 역사를 이해하는 사람들은 파이썬 수학 모듈을 오래된 C 부동 소수점 라이브러리의 래퍼로 즉시 봅니다.따라서 우리는 math.floor()가 플로트 인수를 사용하고 플로트 값을 반환하는 C 표준 라이브러리 플로어()와 동일한 함수라고 생각하지 않습니다.

수치 수학 개념으로 플로어를 사용하는 방법은 위키백과의 주제 페이지인 https://en.wikipedia.org/wiki/Floor_and_ceiling_functions#Notation 에서 1798년으로 거슬러 올라갑니다.

논리적으로 유사한 개념임에도 불구하고 컴퓨터 과학의 은밀한 부동소수점에서 정수 저장 형식 기능은 없었습니다.

이 컨텍스트에서 바닥() 함수는 항상 수학 라이브러리의 모든 함수(대부분)와 마찬가지로 부동 소수점 수치 계산이었습니다.부동 소수점은 정수가 할 수 있는 것 이상입니다.여기에는 부동 소수점 수치 계산을 통해 전파되는 방식에 대해 잘 정의된 +inf, -inf 및 Nan(숫자가 아님)의 특수 값이 포함됩니다.플로어()는 수치 계산에서 Nan 및 +inf 및 -inf와 같은 값을 항상 올바르게 보존합니다.Floor가 int를 반환하면 숫자 floor() 함수가 의도한 전체 개념이 깨집니다. math.floor("float("nan"))가 실제 부동 소수점 숫자 floor() 함수가 되려면 "nan"을 반환해야 합니다.

최근에 Python 교육 비디오에서 다음을 사용하라는 내용을 확인했습니다.

i = math.floor(12.34/3)

정수를 얻기 위해 저는 그 강사가 얼마나 무지한지에 대해 혼자 웃었습니다.하지만 험악한 논평을 쓰기 전에, 저는 몇 가지 테스트를 했고, 충격적이게도, 저는 파이썬의 수치 알고리즘 라이브러리가 int를 반환하고 있다는 것을 발견했습니다.그리고 더 이상한 것은, 제가 생각했던 것은, 분열로부터 의미를 얻는 것에 대한 명백한 답이었습니다.

i = 12.34 // 3

원하는 정수를 얻기 위해 내장된 정수 분할을 사용하는 것은 어떨까요?저의 C 배경에서 볼 때, 그것은 명백한 정답이었습니다.그러나 Python의 정수 분할은 이 경우 FLOAT를 반환합니다.와! 파이썬은 정말 이상한 거꾸로 된 세상입니다.

Python에서 더 나은 대답은 만약 당신이 정말로 int 유형이 필요하다면, 당신은 단지 명시적으로 Python에서 int를 요청해야 한다는 것입니다.

i = int(12.34/3)

그러나 이 바닥()은 음의 무한대를 향해 회전하고 int()는 0을 향해 회전하므로 음의 숫자에 대해 서로 다른 답을 제공합니다.따라서 음수 값이 가능한 경우 응용 프로그램에 필요한 결과를 제공하는 기능을 사용해야 합니다.

하지만 파이썬은 좋은 이유로 다른 짐승입니다.C와는 다른 문제를 해결하려고 합니다.Python의 정적 타이핑은 빠른 프로토타이핑 및 개발에 유용하지만 float와 같은 한 유형의 객체로 테스트된 코드가 int 인수를 통과할 때 미묘하게 실패하고 방법을 찾기 어려울 때 매우 복잡하고 찾기 어려운 버그를 생성할 수 있습니다.이러한 이유로 Python에 대한 많은 흥미로운 선택들이 이루어졌는데, 이는 다른 역사적인 규범보다 예상치 못한 오류를 최소화할 필요성을 제기했습니다.

분할을 변경하여 항상 플로트(또는 어떤 형태의 비인트)를 반환하는 것은 이를 위한 올바른 방향으로의 이동이었습니다.그리고 이와 같은 관점에서, //를 "int divide"가 아닌 floor(a/b) 함수로 만드는 것이 논리적입니다.

MOST 파이썬 코드에서 0에 의한 분할은 수치 계산이 아니라 수학이 잘못되었거나 하나의 오류로 인해 해제된 프로그래밍 버그이기 때문에 float divide를 float("inf")를 반환하는 대신 치명적인 오류로 만드는 것도 현명합니다.실제 버그에서 수 마일 떨어진 곳에서 폭발을 일으키는 "inf" 형태로 숨겨진 오류를 전파하는 대신, 일반적인 파이썬 코드가 버그가 발생했을 때 버그를 잡는 것이 더 중요합니다.

그리고 나머지 언어가 divide나 math.sqrt()와 같이 필요할 때 int를 float에 캐스팅하는 것을 잘 하는 한, math.floor()가 int를 반환하도록 하는 것이 논리적입니다. 왜냐하면 나중에 float로 필요하면 float로 올바르게 변환되기 때문입니다.그리고 만약 프로그래머가 int를 필요로 한다면, 함수는 그들에게 필요한 것을 주었습니다. 수학.floor(a/b)와 a/b는 같은 방식으로 행동해야 하지만, 그렇지 않다는 사실은 아직 일관성을 위해 조정되지 않은 역사의 문제일 뿐입니다.또한 하위 호환성 문제로 인해 "수정"하기가 너무 어려울 수 있습니다.그리고 어쩌면 그렇게 중요하지 않을 수도 있습니다?

파이썬에서 하드코어 수치 알고리즘을 작성하려면 내장된 파이썬 수학 모듈이 아닌 NumPy와 SciPy를 사용하는 것이 정답입니다.

import numpy as np

nan = np.float64(0.0) / 0.0    # gives a warning and returns float64 nan

nan = np.floor(nan)            # returns float64 nan

파이썬은 다른 이유가 있고, 그것을 이해하는 데 약간의 시간이 걸립니다.우리는 이 사례에서 수치 바닥 함수의 역사를 이해하지 못한 OP가 수학적 정수와 실수에 대한 그들의 생각에서 힌트를 반환할 필요가 있었고 기대했다는 것을 알 수 있습니다.이제 Python은 우리의 수학적(대 컴퓨터 과학) 훈련이 의미하는 바를 수행하고 있습니다.이를 통해 NumPy 및 SciPy로 고급 수치 알고리듬의 모든 복잡한 요구를 처리하면서 초보자가 기대하는 작업을 수행할 가능성이 더 높아집니다.저는 파이썬이 어떻게 발전했는지에 대해 항상 깊은 인상을 받습니다. 가끔은 완전히 당황스러울 때도 있지만 말이죠.

언급URL : https://stackoverflow.com/questions/8582741/why-do-pythons-math-ceil-and-math-floor-operations-return-floats-instead-of

반응형