가이드부동 소수점 변환기가 실패하는 이유(및 소수 수학이 문제를 해결하는 방법)
부동 소수점 변환기가 실패하는 이유(및 소수 수학이 문제를 해결하는 방법)
이진 부동 소수점이 이상한 변환 잔차를 생성하는 이유, 이러한 오류가 중요한 경우, 그리고 소수 또는 유리수 산술이 단위 변환기의 신뢰성을 유지하는 방법을 이해하십시오.
고전적인 0.1 + 0.2 문제가 단위를 충족합니다.
대부분의 CPU는 정수가 아닌 숫자를 이진 부동 소수점(IEEE 754)으로 저장합니다. 십진수에서는 단순해 보이는 분수(0.1, 0.001, 2.54)를 이진수로 정확하게 표현할 수 없는 경우가 많습니다. 저장된 값은 표현 가능한 가장 가까운 근사치이며 근사치에 대한 산술은 작은 잔차를 축적합니다.
단위 변환은 해당 값을 반복적으로 곱하고 나눕니다. 인치를 밀리미터로 변환하거나 리터를 입방미터로 변환하면 3 대신 2.9999999997이 표시될 수 있습니다. 물리적 변환 계수는 정확했습니다. 컴퓨터 표현은 그렇지 않았습니다.
많은 디스플레이의 경우 반올림 후에는 차이가 보이지 않습니다. 재무 관련 투여, CNC 도구 경로, 법적 토지 면적 또는 정확한 동일성을 기대하는 자동화된 테스트 주장의 경우 이러한 잔차는 실제 버그가 됩니다.
종이에 정확한 변환 요소는 무엇입니까?
국제 인치는 정확히 25.4mm입니다. 국제발은 정확히 0.3048m이다. 리터는 정확히 0.001m³입니다. 입방센티미터는 일반적인 실험실 의미에서 정확히 1mL입니다(1cm³ = 10⁻⁶m³). 이는 측정이 아니라 정의입니다.
소프트웨어가 25.4를 바이너리 부동 소수점으로 저장하는 경우 변환이 실행되기 전에 이미 약간 잘못되었을 수 있습니다. 다른 부정확한 요소를 곱하면 오류가 복잡해집니다. 엄격한 동일성을 주장하는 왕복 테스트는 알고리즘이 개념적으로 올바른 경우에도 실패합니다.
온도는 오프셋을 추가합니다: 섭씨 ← 켈빈은 273.15를 사용합니다. 해당 상수는 또한 이진수 부동 소수점 근사값인 십진수 값이기도 합니다. 부정확한 오프셋을 추가하면 모든 결과가 이동하기 때문에 Affine 변환은 특히 민감합니다.
실제로 부동 소수점 오류가 나타나는 경우
UI 변환기는 고정된 소수 자릿수로 반올림하여 문제를 숨기는 경우가 많습니다. 사용자는 깨끗한 결과를 볼 수 있으며 내부 소음을 전혀 느끼지 못합니다. 다른 시스템이 원시 부동 소수점(CAD 커널, CSV 내보내기 또는 전체 정밀도 문자열을 비교하는 단위 테스트)을 사용할 때 문제가 나타납니다.
연쇄 변환은 문제를 증폭시킵니다. 각 단계에서 이진 수레를 사용하여 마일 → 야드 → 피트 → 인치 → 밀리미터 → 미터로 가는 것은 고정밀 계수를 사용하여 1마일 → 미터로 변환하는 것보다 나쁩니다. 각 홉은 중간 값을 다시 반올림합니다.
제곱과 세제곱의 양은 오류를 더욱 악화시킵니다. 면적과 부피는 길이 척도를 곱하므로 (1+ε)ⁿ를 확장하면 길이의 작은 상대 오차가 면적이나 부피에 대한 상대적 측면에서 2~3배 더 커집니다.
십진수, 유리수 및 고정 소수점 대안
십진수 라이브러리(예:decimal.js, Big.js 또는 언어 기본 십진수)는 숫자를 10진법으로 저장합니다. 0.3048 및 0.001과 같은 정확한 소수점 인수는 선택한 정밀도 내에서 정확하게 유지됩니다. 정확성을 중요하게 생각하는 단위 변환기는 종종 십진수 기본 단위를 통해 변환합니다.
유리수 산술은 인수를 정수의 분수로 저장합니다. 1인치 = 127/5000미터가 정확히면(25.4mm = 127/5000m이기 때문에) 곱셈은 정확하게 취소될 수 있습니다. Rationals는 순수한 규모 변환에 이상적입니다. 오프셋은 여전히 온도에 대한 세심한 취급이 필요합니다.
고정 소수점 수학은 나노미터, 마이크로리터 또는 1/1000인치 등 가장 작은 눈금의 정수 개수까지 모든 것을 확장합니다. 정수 연산은 오버플로될 때까지 정확합니다. 이는 명확한 측정량을 갖춘 도메인에 적합합니다.
신뢰할 수 있는 변환기를 위한 실제 규칙
성급하게 입력한 이진 부동 소수점이 아닌 소수 또는 유리수로 정확한 법적 요소를 저장합니다. 입력 → 기본 → 출력을 가능한 한 적은 단계로 변환합니다. 사람을 대상으로 형식을 지정할 때만 반올림하고 반올림 모드를 문서화하세요.
바이너리 부동 소수점에 대해 엄격한 동등성을 갖는 변환기를 테스트하지 마십시오. 절대 또는 상대 허용오차 내에서 비교하거나, 명시된 정밀도로 소수 문자열 형식을 비교하세요. 1인치 = 25.4mm와 같이 알려진 정확한 쌍을 사용하는 최적 테스트를 선호합니다.
계산기 UI를 구축하는 경우 유용할 만큼 충분한 정밀도를 표시하되 부동 노이즈가 신호처럼 보일 정도로 많은 자릿수를 표시하지 마십시오. 부동 소수점을 통해 변환한 후 소수점 12자리를 표시하는 길이 도구는 표현 오류를 알리는 것입니다.
바이너리 플로트가 여전히 괜찮은 경우
대략적인 비교, 게임, 데이터 시각화 및 많은 과학적 시뮬레이션에서는 모델 불확실성이 표현 오류를 축소시키기 때문에 부동 오류를 허용합니다. 중요한 것은 당신의 관용을 아는 것입니다. 밀리미터가 중요한 경우 플로트에는 규율이나 교체가 필요합니다.
하드웨어 가속 및 GPU 파이프라인은 종종 부동을 강제합니다. 이러한 경우 CPU 또는 서버에서 신뢰할 수 있는 십진수 변환을 유지하고 GPU 부동 소수점을 디스플레이 또는 중간 근사치로 처리하십시오.
좋은 엔지니어링은 숫자 표현을 숫자로 내리는 결정과 일치시키는 것입니다. 제조, 의학 및 법적 계측을 위한 단위 변환은 소수 또는 유리수 계산에 적합합니다. 도시 온도를 변환하는 날씨 위젯은 그렇지 않습니다. 확실하지 않은 경우 더 엄격한 표현을 선택하십시오. 소수의 성능 비용은 일반적으로 조용한 왕복 버그 비용보다 작습니다.
관련 변환기
자주 묻는 질문
왜 앞뒤로 변환하면 내 번호가 변경되나요?
이진 부동 소수점은 많은 소수 요소를 정확하게 나타낼 수 없습니다. 곱하거나 나눌 때마다 작은 반올림 오류가 추가됩니다. 부동 소수점을 통한 왕복 변환은 변환 요소가 개념적으로 정확하더라도 원래 비트를 복원하지 못하는 경우가 많습니다.
단위 변환에 이중 정밀도가 충분합니까?
이중 정밀도(float64)는 디스플레이 반올림 후 많은 일상적인 변환에 충분하지만 비트 안정적인 왕복, 법적 계측 또는 엄격한 자동화 테스트가 필요한 경우 정확한 소수점 이하 자릿수를 대체할 수는 없습니다. 신뢰할 수 있는 변환기에는 소수 또는 유리수를 선호합니다.
테스트에서 변환기 결과를 어떻게 비교해야 합니까?
선언된 정밀도로 비교하고, 십진수 문자열 동등성을 사용하거나, 절대 및 상대 허용오차를 주장하십시오. 여러 산술 단계 후에 정확한 이진 동일성을 기대하지 마십시오.