x64의 Python 2.7.9에서 다음 동작이 표시됩니다.
>>> float("10"*(2**28))
inf
>>> float("10"*(2**29))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: could not convert string to float: 10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010
>>> float("0"*(2**33))
0.0
>>> float("0." + "0"*(2**32))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: could not convert string to float: 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
더 깊은 근거가없는 한 나는 이것이 최소한의 놀라움을 위반합니다. ValueError가 발생했을 때 "10"*(2**29)
매우 긴 문자열에 대한 제한이라고 생각했지만 "0"*(2**33)
작동했습니다. 무슨 일이야? 이 동작이 POLA 버그가 아닌 이유를 누구든지 정당화 할 수 있습니까 (아마도 상대적으로 관련없는 버그 인 경우)?
베이스를 추론 할 때 0은 건너 뛰기 때문에
저는 이와 같은 질문에 대해 제가 가장 좋아하는 참조 구현을 찾고 싶습니다.
증거
Casevh는 의견에 큰 직감을 가지고 있습니다. 관련 코드는 다음과 같습니다 .
for (bits_per_char = -1; n; ++bits_per_char)
n >>= 1;
/* n <- total # of bits needed, while setting p to end-of-string */
while (_PyLong_DigitValue[Py_CHARMASK(*p)] < base)
++p;
*str = p;
/* n <- # of Python digits needed, = ceiling(n/PyLong_SHIFT). */
n = (p - start) * bits_per_char + PyLong_SHIFT - 1;
if (n / bits_per_char < p - start) {
PyErr_SetString(PyExc_ValueError,"long string too large to convert");
return NULL;
경우 p
초기에 문자열로 포인터로 설정됩니다. PyLongDigitValue
테이블 을 보면 0이 명시 적으로 0에 매핑되어 있음을 알 수 있습니다.
파이썬은 특정 염기의 변환을 최적화하기 위해 많은 추가 작업을 수행합니다 ( 바이너리 변환에 대한 재미있는 200 줄의 주석이 있습니다 !). 그래서 올바른 염기를 먼저 추론하기 위해 많은 작업을 수행합니다. 이 경우에는 밑수를 추론 할 때 0을 건너 뛸 수 있으므로 오버플로 계산에 포함되지 않습니다.
사실, 우리는이 float를 저장하는 데 필요한 비트 수를 확인하고 있지만, 파이썬은이 계산에서 선행 0을 제거 할만큼 똑똑합니다. 구현 전반에 걸쳐이 동작을 보장하는 float 함수의 문서에는 아무것도 표시되지 않습니다. 그들은 불길하게 말한다
가능한 경우 문자열 또는 숫자를 부동 소수점 숫자로 변환합니다.
이것이 작동하지 않는 경우
당신이 쓸 때
float("0." + "0"*(2**32))
초기에 기초에 대한 구문 분석을 중지합니다. 나머지 모든 0은 비트 길이 계산에서 고려되며 ValueError
유사한 파싱 트릭
다음 은 공백이 무시 된 float 클래스 의 유사한 경우 입니다 (이 디자인 선택에 대한 작성자의 의도에 대한 흥미로운 의견).
while (Py_ISSPACE(*s))
s++;
/* We don't care about overflow or underflow. If the platform
* supports them, infinities and signed zeroes (on underflow) are
* fine. */
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다