처음 가 0.1 + 0.2 === 0.3 버그가 생산에서 나를 물었고,나는 대부분의 개발자들이하는 일을했다: 나는 검색하고,찾았다 & quot;floating point is weird," 그리고 계속 나아 갔다. 내가 실제로 비트를보고 왜 이해하기까지는 몇 년이 걸렸다. 일단 내가 한 번,숫자 버그의 전체 범주는 신비하지 않게되었다. 이 가이드는 IEEE 754 변환기가 당신에게 보여주는 것을 통해 걷는다,을 사용하여 IEEE 754 변환기 Toolz.dev에서, 그리고 왜 부호, 지수, 가수를 쳐다보는 것이 컴퓨터가 소수를 저장하는 방법에 대한 실제 직관을 구축하는 가장 빠른 방법입니다.
TL;DR: 컴퓨터는 부동 소수점 숫자를 IEEE 754 표준에 따라 부호, 2의 거듭제곱 및 유효 분수 숫자로 저장합니다. IEEE 754 변환기는 3.14159와 같은 십진수를 해당 정확한 비트로 인코딩하고 비트를 다시 값으로 디코딩합니다. 그만큼 IEEE 754 변환기 단정밀도와 이중정밀도를 위해 기호, 지수, 가수가 구분된 상태로 브라우저에서 완전히 수행됩니다.
IEEE 754 란 무엇인가?
IEEE 754는 1985년에 처음 발표되어 다음과 같이 개정된 표준입니다 IEEE 754-2019이는 컴퓨터가 이진수로 부동 소수점 숫자를 표현하는 방식을 정의합니다. 거의 모든 CPU, GPU 및 프로그래밍 언어가 이를 따릅니다. 이것이 바로 a double c,java, Python,JavaScript 에서 동일하게 동작합니다. 사람들이 "floating point,"라고 말할 때,거의 항상 IEEE 754 바이너리 부동 소수점을 의미합니다.
핵심 아이디어는 숫자가 세 부분으로 저장된다는 것입니다. 양수 또는 음수라고 말하는 부호 비트가 있습니다. 값을 2 승으로 조정하는 지수가 있습니다. 그리고 분수 또는 유효 숫자라고도하는 가수가 정확한 숫자를 합치면 정규 숫자는 부호 곱하기 1.mantissa 곱하기 2 의 지수입니다. 그것은 과학적 표기법,기본 2 에서 고정 된 비트 수로 포장됩니다.
매일 만나는 두 가지 형식은 binary32 라고 하는 단일 정밀도와 binary64 라고 하는 이중 정밀도입니다. 단일은 1 부호 비트, 8 지수 비트 및 23 가수 비트를 사용하여 총 32 비트를 사용합니다. 이중은 1 부호 비트, 11 지수 비트 및 52 가수 비트를 사용하여 총 64 비트를 사용합니다. 이중은 대부분의 언어에서 기본 부동 소수점 유형입니다; 단일은 GPU 및 메모리 감지 코드에서 일반적입니다.
IEEE 754 변환기는 실제로 무엇을합니까?
IEEE 754 변환기는 숫자를 가지고 그 정확한 비트 패턴을 보여줍니다, 그 세 개의 필드로 분할, 16 진수 형태와 비트로부터 다시 읽은 값과 함께. 그것은 두 가지 방법으로 작동합니다: 그것을 인코딩하는 십진수를 입력하거나, 이진 또는 육각 비트 패턴을 붙여서 그것이 나타내는 숫자로 다시 디코딩합니다.
Toolz.dev 에서 워크플로는 짧습니다. 단일 또는 이중 정밀도를 선택합니다. 입력이 십진수,16 진수 비트 패턴 또는 이진수 비트 패턴인지 선택합니다. 값을 입력합니다. 도구는 부호 비트,지수 필드,가수, 전체 비트,16 진수,편향 및 편향되지 않은 지수 모두,그리고 정확한 저장된 값을 보여줍니다. 모든 필드에는 복사 버튼이 있습니다.
이 모든 것을 살펴봐야 하는 이유는,언어가 인쇄하는 숫자를 신뢰하기 보다는,인쇄된 숫자가 누락에 의해 놓여있기 때문입니다. 본체가 표시될 때 0.1를,여러분에게 둥글고 친근한 렌더링을 보여주고 있습니다. 비트는 무엇이 정말로 저장되어 있는지를 말해주고,그 둘의 차이는 부동 소수점 버그가 사는 곳입니다.
왜 0.1 더하기 0.2 는 0.3 이 아닌가요?
이것이 정준예이고,변환기는 그것을 구체화시킵니다. 0,1 이라는 값은 이진 부동점으로 정확히 나타낼 수 없습니다. 같은 이유로 1/3 은 십진수로 정확히 쓸 수 없습니다. 10 진법에서 1/3 은 0,3333...영원히 2 진법에서 0,1 은 결코 끝나지 않는 반복 분수이므로 52 개의 가수 비트에 맞도록 반올림해야 합니다.
0,1 에 대한 더블을 디코딩하고 비트가 실제로 보유하는 값은 0,10000000000005551115123125782702181583404541015625 입니다. 0,2 에 대한 더블은 마찬가지로 머리카락이 너무 큽니다. 두 개의 둥근 값을 추가하면 결과는 0,3 보다 작은 비트이지만 0,3 에 대한 더블은 아주 작은 비트이므로 둘이 같지 않습니다. 각 단계는 IEEE 754 가 요구하는 것을 정확히 수행하고 있으며 변환기는 믿음으로 취하는 대신 그 일이 일어나는 것을 지켜 볼 수 있습니다.
일단 이것을 보았다면,고치는 자연스럽게 따라옵니다: 정확한 동등성을 위해 플로트를 비교하지 마십시오. 작은 허용 오차 내에서 비교하거나,정수 센트를 돈으로 사용하거나,정확한 십진수 산술이 필요할 때 십진수 라이브러리를 사용하십시오. 버그는 결코 추가 된 십진수 분수를 정확하게 저장하는 이진 형식을 기대하는 것이 었습니다.
부호, 지수, 가수는 무엇입니까?
각 필드에는 특정 작업이 있으며 변환기는 세 가지 모두에 레이블을 지정합니다.
부호 비트는 가장 간단합니다: 0 은 양수,1 은 음수를 의미합니다. 부호가 별도의 비트이기 때문에 IEEE 754 는 양수와 음수 0 을 모두 가지며,비교에서는 동일하게 동작하지만 다른 비트를 전달합니다.
지수 필드는 2 의 거듭제곱을 저장하지만,바이어스가 추가되어 별도의 부호 없이 음의 지수를 나타낼 수 있습니다. 바이어스는 단정밀도의 경우 127 이고,이중의 경우 1023 입니다. 따라서 단정밀도의 경우 저장된 127 지수 필드는 0 의 실제 지수를 의미합니다. Toolz.dev 변환기는 두 숫자를 모두 보여줍니다: 비트에 사는 편향된 값과 실제로 적용되는 2 의 편향되지 않은 거듭제곱. 그 구별은 많은 사람들을 넘어뜨리는데,이것이 바로 도구가 머릿속에서 빼게 하는 것이 아니라 철자를 쓰는 이유입니다.
가수는 유효숫자의 분수 부분을 보유합니다. 정규숫자의 경우 저장되지 않는 암시된 선행 1 이 있습니다. 왜냐하면 정규화된 이진 유효숫자는 항상 1 로 시작하기 때문에 형식은 생략함으로써 자유 정밀도를 얻습니다. 이것이 바로 단일 정밀도가 약 7 개의 십진수를 제공하고 이중은 약 15 에서 16 을 제공하는 이유입니다. 비록 가수의 필드가 23 과 52 비트임에도 불구하고 말이죠.
두 형식이 필드별로 정렬되는 방법은 다음과 같습니다:
| 재산 | 싱글 (binary32) | 더블 (binary64) |
|---|---|---|
| 총 비트 | 32 | 64 |
| 부호 비트 | 1 X 1000 X 1000 X 1000 X 1000 X 1000 X 1000 X 1000 X 1000 X 1000 X 1000 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 1 | 1 X 1000 X 1000 X 1000 X 1000 X 1000 X 1000 X 1000 X 1000 X 1000 X 1000 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 100 X 1 |
| 지수 비트 | 8 X 1000 X 1000 X 1000 X 1000 X 1000 X 100 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 X 80 | 11 |
| 가수 비트 | 23 | 52 |
| 지수 편향 | 127 | 1023 |
| 대략적인 십진수 | 7 X 1000 X 1000 X 1000 X 100 X 100 X 100 X 100 X 100 X 100 X 70 X 100 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X 70 X | 15~16 |
| 일반적인 이름 | 떠다니다 | 더블 |
어떻게 비트를 다시 십진수로 변환합니까?
디코딩은 인코딩만큼 유용하며 메모리 덤프,바이너리 파일 형식 또는 원시 플로트를 저장하는 네트워크 프로토콜에서 값을 읽는 방법입니다. 입력 유형을 Hex 또는 Binary 로 설정하고 정밀도가 기대하는 정확한 비트 패턴을 붙여 넣습니다: 8 개의 16 자리 또는 32 비트의 단일,16 개의 16 자리 또는 64 비트의 이중.
예를 들어 단정밀도 16진수입니다 40490FDB 원주율에 가장 가까운 플로트인 3.1415927 로 디코딩합니다. 변환기는 또한 선택 사항을 허용합니다 0x 접두사와 공백 및 밑줄을 무시하므로 그룹화된 바이트를 찾을 때 붙여넣을 수 있습니다. 잘못된 자릿수를 주면 조용히 자르는 대신 정밀도에 필요한 수를 정확하게 알려줍니다. 이는 더 많은 도구가 작성하기를 바라는 오류 메시지의 종류입니다.
이 디코딩 방향은 일반 방향과 자연스럽게 쌍을 이룹니다 숫자 베이스 변환기 부동 소수점 해석 없이 소수점, 16진수, 2진수, 8진수 사이에서 값을 이동해야 하는 경우 이진 변환기 숫자보다는 텍스트로 작업 할 때. 나는 그들이 내 책갈피의 같은 구석에 살 정도로 세 가지 모두에 자주 도달합니다.
무한대, NaN, 0은 어떻게 표현되나요?
특별한 값은 IEEE 754 가 영리해지는 곳이며,변환기는 패턴을 외울 필요가 없도록 각 경우를 식별합니다.
지수 필드는 스위치 역할을 합니다. 모든 지수 비트가 1 일 때,당신은 특별한 범위에 있습니다: 모든 0 가수는 무한대를 의미하고,0 이 아닌 모든 가수는 숫자가 아닌 NaN 을 의미합니다. 양수 및 음수 무한대는 부호 비트에 의해서만 다릅니다. NaN 은 0 나누기 0 또는 음수의 제곱근과 같은 연산에서 얻는 것으로,자체와 같지 않다는 유명한 속성을 가지고 있습니다.
모든 지수 비트가 0 일 때,당신은 다른 특별한 범위에 있습니다: 모든 0 가수는 부호 비트에 따라 양수 또는 음수이며,0 이 아닌 가수는 비정규 숫자입니다. 준정규는 0 과 가장 작은 정규 숫자 사이의 간격을 채우고,매우 작은 크기를 나타내는 능력에 대한 거래 정밀도. 그들은 1 의 유효 지수에서 편향을 뺀 값을 사용하고,변경되지 않은 지수를 보여줄 때 변환기가 설명하는 암시 된 선행 1 을 떨어 뜨립니다.
지수장이 모두 0 도 아니고 모두 1 도 아닌 다른 모든 것은 정상적인 숫자입니다. 비트 패턴을 흘끗 보고 이 다섯 가지 경우 중 어느 경우를 보고 있는지 즉시 알 수 있다는 것은 계산이 예상하지 못한 값을 생성할 때 진정한 디버깅 초능력입니다.
실제로 언제 이것이 필요합니까?
한번 알고 보면 짐작할 수 있는 것보다 더 자주 필요합니다. 반올림 오류로 인해 숫자 결과가 꺼졌을 때 도달하고 값이 정확히 표현 가능한지 확인하고 싶습니다. 이진 직렬화기,파일 형식 또는 플로트를 저장하는 와이어 프로토콜을 작성하거나 디버깅할 때 이를 사용하므로 바이트가 의도한 것과 일치하는지 확인할 수 있습니다. 예를 들어 GPU 셰이더가 사용할 수 있는지 여부를 결정하는 등 단정밀도와 이중정밀도를 비교할 때 없어서는 안 될 요소입니다 float 너무 많은 정확성을 잃지 않고 말이죠. 그리고 제가 컴퓨터 건축에 대해 알고 있는 가장 명확한 교육 보조 도구 중 하나입니다. 왜냐하면 분야를 보는 것은 추상적인 표준을 실체화시키기 때문입니다.
만약 여러분이 제가 하는 방식으로 스택을 가로질러 빌드한다면,부동점은 놀라운 곳에 나타납니다: Laravel API 의 가격 계산,React 의 캔버스 애니메이션,좌표를 망가뜨리는 CSV 내보내기. 스토리지 포맷을 이해하는 것은 그 모든 것에 걸쳐 성과를 내는 작은 투자와 같은 도구들이 어떻게 더 넓은 키트에 들어맞는지에 대해 썼습니다 웹 개발자 툴킷, 그리고 숫자 베이스 변환기 가이드 그리고 바이너리 번역기 가이드 인접한 하위 수준 변환을 더 깊이 있게 다룹니다.
부동 소수점 정밀도의 한계는 무엇입니까?
비트를 볼 수 있게 되면 포맷의 한계는 추상적이기를 멈춥니다. 더블은 52 개의 저장된 가수 비트와 암시된 선행 1 을 더한 값을 가지게 되며,이는 대략 15 에서 16 개의 유효 십진수로 작동합니다. 그것을 지나쳐 정밀도는 조용히 증발합니다. 더블이 나타낼 수 있는 가장 큰 정수는 여전히 정확한 사이의 모든 값으로 2 의 53 제곱,즉 9007199254740992 입니다. 여기에 하나를 더하면 결과는 다시 반올림됩니다. 왜냐하면 다음 표현 가능한 값은 하나가 아니라 두 개 떨어져 있기 때문입니다. 이것이 모든 숫자에 더블을 사용하는 언어,그 중 자바스크립트가 a 를 노출하는 이유입니다 Number.MAX_SAFE_INTEGER 정확히 그 값에서 일정하며, JSON 번호로 전송된 대규모 데이터베이스 ID가 자동으로 손상될 수 있는 이유.
하나의 표현 가능한 값과 다음 값 사이의 간격은 마지막 위치의 단위 또는 ULP라고하며 크기가 커짐에 따라 커집니다. 1.0 근처에서 간격은 작습니다; 10 억 근처에서 몇 백입니다; 최대 이중 근처, 약 1.8 곱하기 10 의 308 번째, 이웃 사이의 간격은 천문학적으로 큽니다. 변환기는 이것을 보이게합니다: 근처에있는 두 개의 큰 숫자를 인코딩하면 단순히 그 사이에 표현이 없기 때문에 종종 동일한 비트를 공유한다는 것을 알게됩니다. ULP를 이해하는 것은 형식이 줄 수있는 것보다 더 많은 해상도를 기대하지 못하게하는 것입니다.
관련된 함정은 치명적인 취소입니다. 거의 동일한 두 부동 소수점 숫자를 빼면 앞자리 숫자가 취소되고 처음부터 정확도가 가장 낮은 부분이었던 하위 비트가 남습니다. 결과는 각 입력이 정확해 보였음에도 불구하고 반올림 오류로 지배될 수 있습니다. 이것이 바로 수치적으로 신중한 코드가 가까운 수량을 빼지 않도록 작업을 재정렬하는 이유이며,순진한 루프에서 긴 부동 소수점 목록을 합산하면 Kahan 합산과 같은 더 나은 알고리즘이 피할 수 있는 오류가 누적되는 이유입니다.
실용적인 테이크 아웃은 일관성이 있습니다. 돈을 플로트로 저장하지 마십시오; 0.10 과 같은 값은 정확히 표현할 수 없으며 수천 건의 거래에서 오류가 복합적으로 발생하기 때문에 정수 센트 또는 소수 유형을 사용하십시오. 정확한 동등성을 가진 플로트를 비교하지 마십시오; 문제에 맞는 공차 범위 내에서 비교하십시오. 그리고 매우 큰 정수가 왕복 여행에서 살아남아야 할 때,문자열로 유지하거나 이중을 보유하는 것을 신뢰하기보다는 임의 정밀도 정수 유형을 사용하십시오. 이러한 각 규칙은 변환기가 형식이 작동하는 이유를 보여 주면 기억하기가 더 쉽습니다.
자주 묻는 질문
십진수를 IEEE 754 로 변환하려면 어떻게 해야 하나요?
단일 또는 이중 정밀도를 선택하고 입력 유형을 Decimal 에 유지하고 번호를 입력한 후 변환합니다. 이 도구는 값을 IEEE 754 비트 패턴으로 인코딩하고 부호 비트,지수 필드,가수, 전체 이진수 및 16 진수 모두 브라우저에서 실행됩니다.
단정밀도와 이중정밀도의 차이점은 무엇입니까?
단정밀도 (binary32) 는 32 비트를 사용한다: 1 개의 부호, 8 개의 지수, 23 개의 가수를 사용하여 약 7 개의 십진수 자리의 정밀도를 제공한다. 이중정밀도 (binary64) 는 64 비트를 사용한다: 1 개의 부호, 11 개의 지수, 52 개의 가수를 사용하여 약 15 에서 16 개의 이중은 대부분의 언어에서 기본 float 타입이다; 싱글은 GPU와 메모리 제약 코드에서 일반적이다.
왜 0.1 은 정확한 값으로 변환되지 않는가?
0.1 은 1/3 이 유한 소수점이 없는 것처럼 이진 부동 소수점에서도 유한한 표현이 없습니다. 가장 가까운 표현 가능한 이중은 0.1000000000000055511151231257827021181583404541015625 입니다. 변환기는 비트에서 다시 읽은 저장된 값을 표시하므로 0.1 + 0.2 와 같은 반올림 놀라움이 0.3 과 같지 않게 하는 작은 차이를 볼 수 있습니다.
부호, 지수, 가수는 무엇입니까?
부호 비트는 양수 0,음수 1 입니다. 지수 필드는 바이어스가 추가된 2 의 거듭제곱 (싱글은 127,더블은 1023) 을 저장합니다. 이것이 바로 도구가 비트의 바이어스된 값과 적용되는 바이어스되지 않은 거듭제곱을 모두 표시하는 이유입니다. 가수는 정규 숫자에 대해 암시된 선행 1 과 함께 유효 숫자의 분수 부분을 보유합니다.
IEEE 754 비트를 다시 십진수로 변환할 수 있나요?
예. 입력 유형을 Hex 또는 Binary 로 설정하고 정확한 비트 패턴을 붙여 넣습니다: 8 개의 16 진수 또는 32 비트는 단일 정밀도,16 개의 16 진수 또는 64 비트는 이중으로 합니다. 도구는 이를 디코딩하고 전체 필드 분석과 함께 나타내는 소수 값을 보여줍니다.
무한대, NaN, 0은 어떻게 표현되나요?
모든 지수 비트가 1 일 때,모든 0 가수는 무한대를 의미하고 0 이 아닌 가수는 NaN 을 의미합니다. 모든 지수 비트가 0 일 때,모든 0 가수는 0 (부호 비트에 따라 양수 또는 음수) 이고 0 이 아닌 가수는 비정규 변환기는 이러한 각 경우에 레이블을 지정합니다.
민감한 숫자에 이 도구를 사용하는 것이 안전한가요?
예. 변환은 브라우저에서 전적으로 JavaScript 로 실행됩니다. 네트워크 요청이 입력을 전달하지 않으며,아무것도 저장되지 않으며,페이지가 로드되면 도구가 오프라인으로 작동하므로 입력한 모든 값이 장치에 유지됩니다.
변환기는 어떤 16 진수 형식을 기대합니까?
선택적인 0x 접두사와 그룹화를 위한 공백 또는 밑줄이 있는 일반 16 진수 숫자는 무시됩니다. 단정밀도는 8 개의 16 진수를 기대하고,이중정밀도는 16 을 기대합니다. 예를 들어,40490FDB 는 단정밀도 파이 (3,1415927) 입니다.
무료로 비트를 직접 탐색해 보세요 IEEE 754 변환기. 그것은 아무것도를 올려주기하지 않는 상태에서 당신의 브라우저에서 단일 및 이중 정밀도 부유물을 전부 암호로 고치고 해독합니다.



