IBM 16진 부동소수점

십육진법 부동소수점(, 현재 IBM에서는 HFP라고 부름)은 IBM System/360 컴퓨터에서 처음 도입되었고, 이후 해당 아키텍처를 기반으로 하는 장치와 System/360과 응용 프로그램 호환성을 목표로 하는 장치에서 지원되는 부동소수점 숫자를 인코딩하는 형식이다.IBM System/360 Principles of Operation, IBM Publication A22-6821-6, Seventh Edition (January 13, 1967), pp.41-50IBM System/370 Principles of Operation, IBM Publication GA22-7000-4, Fifth Edition (September 1, 1975), pp.157-170z/Architecture Principles of Operation, IBM Publication SA22-7832-01, Second Edition (October, 2001), chapter 9 ff.

IEEE 754 부동소수점과 비교하여 HFP 형식은 더 긴 유효숫자와 더 짧은 지수를 갖는다. 모든 HFP 형식은 64의 편향을 가진 7비트 지수를 갖는다. 표현 가능한 숫자의 정규화된 범위는 16−65에서 1663(약 5.39761 × 10−79에서 7.237005 × 1075)까지이다.

이 숫자는 다음 공식으로 표현된다: (−1)부호 × 0.유효숫자 × 16지수−64.

 단정밀도 32비트 
단정밀도 HFP 숫자(IBM에서는 "짧은" 형식이라고 부름)는 32비트 워드에 저장된다.

{|
|- style="text-align:center"
|style="width:20px"|1
|style="width:20px"|
|style="width:50px"|7
|style="width:20px"|
|style="width:20px"|
|style="width:210px"|24
|style="width:20px"|
|style="text-align:left"|(비트 너비)
|- style="text-align:center"
|colspan="1" style="text-align:center;background-color:#FC9"|S
|colspan="3" style="text-align:center;background-color:#99F"|Exp
|colspan="3" style="text-align:center;background-color:#9F9"|Fraction
|colspan="1" style="text-align:center;background-color:#FFF"| 
|- style="text-align:center"
|31
|30
|...
|24
|23
|...
|0
|align="left"|(비트 인덱스)*
|-
|colspan="8"| * IBM 문서에서는 비트를 왼쪽에서 오른쪽으로 번호 매기며, 최상위 비트를 비트 번호 0으로 지정한다.
|}

이 형식에서는 초기 비트가 억제되지 않으며, 기수점(십육진법)은 유효숫자(IBM 문서 및 그림에서는 분수)의 왼쪽에 설정된다.

밑이 16이므로, 이 형식의 지수는 IEEE 754에서와 동등한 지수 범위(2진법에서 9개의 지수 비트 필요)를 갖기 위해 약 두 배 더 크다.

 예시 
값 −118.625를 HFP 단정밀도 부동소수점 값으로 인코딩하는 것을 고려해 보자.

값은 음수이므로 부호 비트는 1이다.

값 118.62510는 2진법으로 1110110.1012이다. 이 값은 가장 왼쪽 숫자가 0이 될 때까지 소수점을 왼쪽으로 네 비트(16진수 한 자리)씩 이동하여 0.011101101012로 정규화된다. 남은 가장 오른쪽 자리는 0으로 채워져 .0111 0110 1010 0000 0000 00002의 24비트 분수가 된다.

정규화된 값은 소수점을 왼쪽으로 두 16진수 자리만큼 이동하여 16+2의 승수와 지수를 얻는다. 지수(+2)에 +64의 편향이 더해져 +66이 되며, 이는 100 00102이다.

부호, 지수와 편향, 정규화된 분수를 결합하면 다음과 같은 인코딩이 생성된다.

{|
|- style="text-align:center"
|style="width:20px;text-align:center;background-color:#FC9"|S
|style="width:90px;text-align:center;background-color:#99F"|Exp
|style="width:250px;text-align:center;background-color:#9F9"|Fraction
|style="text-align:center;background-color:#FFF"| 
|- style="text-align:center"
|style="text-align:center;background-color:#FEC"|
|style="text-align:center;background-color:#CCF"|
|style="text-align:center;background-color:#CFC"|
|style="text-align:center;background-color:#FFF"| 
|}

다른 말로 표현하면, 표현된 숫자는 −0.76A00016 × 1666 − 64 = −0.4633789… × 16+2 = −118.625이다.

 표현 가능한 가장 큰 수 
{|
|- style="text-align:center"
|style="width:20px;text-align:center;background-color:#FC9"|S
|style="width:90px;text-align:center;background-color:#99F"|Exp
|style="width:250px;text-align:center;background-color:#9F9"|Fraction
|style="text-align:center;background-color:#FFF"| 
|- style="text-align:center"
|style="text-align:center;background-color:#FEC"|
|style="text-align:center;background-color:#CCF"|
|style="text-align:center;background-color:#CFC"|
|style="text-align:center;background-color:#FFF"| 
|}

표현된 숫자는 +0.FFFFFF16 × 16127 − 64 = (1 − 16−6) × 1663 ≈ +7.2370051 × 1075이다.

 가장 작은 양의 정규화된 수 
{|
|- style="text-align:center"
|style="width:20px;text-align:center;background-color:#FC9"|S
|style="width:90px;text-align:center;background-color:#99F"|Exp
|style="width:250px;text-align:center;background-color:#9F9"|Fraction
|style="text-align:center;background-color:#FFF"| 
|- style="text-align:center"
|style="text-align:center;background-color:#FEC"|
|style="text-align:center;background-color:#CCF"|
|style="text-align:center;background-color:#CFC"|
|style="text-align:center;background-color:#FFF"| 
|}

표현된 숫자는 +0.116 × 160 − 64 = 16−1 × 16−64 ≈ +5.397605 × 10−79이다.

 0 
{|
|- style="text-align:center"
|style="width:20px;text-align:center;background-color:#FC9"|S
|style="width:90px;text-align:center;background-color:#99F"|Exp
|style="width:250px;text-align:center;background-color:#9F9"|Fraction
|style="text-align:center;background-color:#FFF"| 
|- style="text-align:center"
|style="text-align:center;background-color:#FEC"|
|style="text-align:center;background-color:#CCF"|
|style="text-align:center;background-color:#CFC"|
|style="text-align:center;background-color:#FFF"| 
|}

0 (0.0)은 모든 비트가 0인 정규화된 형태로 표현되며, 이는 산술적으로 +0.016 × 160 − 64 = +0 × 16−64 ≈ +0.000000 × 10−79 = 0의 값이다. 모든 비트가 0인 분수가 주어지면, 양수 또는 음수 부호 비트와 0이 아닌 편향된 지수의 어떤 조합이든 산술적으로 0과 같은 값을 생성한다. 그러나 CPU 하드웨어에 의해 0에 대해 생성된 정규화된 형태는 모든 비트가 0이다. 이는 모든 세 가지 부동소수점 정밀도 형식에 해당한다. 다른 지수 값과의 덧셈 또는 뺄셈은 결과의 정밀도를 잃을 수 있다.

 정밀도 문제 
밑이 16이기 때문에 2진 유효숫자에는 최대 3개의 선행 0 비트가 있을 수 있다. 이는 숫자를 2진법으로 변환할 때 정밀도가 21비트밖에 되지 않을 수 있음을 의미한다. "흔들리는 정밀도" 효과 때문에 일부 계산이 매우 부정확해질 수 있다. 이로 인해 상당한 비판을 받았다.

부정확성의 좋은 예는 십진수 값 0.1의 표현이다. 이 값은 정확한 2진 또는 16진 표현을 갖지 않는다. 16진 형식에서는 0.19999999...16 또는 0.0001 1001 1001 1001 1001 1001 1001...2로 표현된다. 즉:

{|
|- style="text-align:center"
|style="width:20px;text-align:center;background-color:#FC9"|S
|style="width:90px;text-align:center;background-color:#99F"|Exp
|style="width:250px;text-align:center;background-color:#9F9"|Fraction
|style="text-align:center;background-color:#FFF"| 
|- style="text-align:center"
|style="text-align:center;background-color:#FEC"|
|style="text-align:center;background-color:#CCF"|
|style="text-align:center;background-color:#CFC"|
|style="text-align:center;background-color:#FFF"| 
|}

이는 정밀도가 21비트밖에 되지 않는 반면, 2진법 버전은 24비트의 정밀도를 갖는다.

6개의 16진수 정밀도는 대략 6개의 10진수와 동일하다 (즉, (6 - 1) log10(16) ≈ 6.02). 단정밀도 16진수 부동소수점을 10진수 문자열로 변환하고 다시 동일한 16진수 부동소수점 값으로 변환하려면 최소 9개의 유효 숫자(즉, 6 log10(16) + 1 ≈ 8.22)가 필요하다.

 배정밀도 64비트 
배정밀도 HFP 형식(IBM에서는 "긴" 형식이라고 부름)은 "짧은" 형식과 동일하지만, 분수 필드가 더 넓고 배정밀도 숫자는 이중 워드(8바이트)에 저장된다.

{|
|- style="text-align:center"
|style="width:20px"|1
|style="width:20px"|
|style="width:50px"|7
|style="width:20px"|
|style="width:20px"|
|style="width:320px"|56
|style="width:20px"|
|style="text-align:left"|(비트 너비)
|- style="text-align:center"
|colspan="1" style="text-align:center;background-color:#FC9"|S
|colspan="3" style="text-align:center;background-color:#99F"|Exp
|colspan="3" style="text-align:center;background-color:#9F9"|Fraction
|colspan="1" style="text-align:center;background-color:#FFF"| 
|- style="text-align:center"
|63
|62
|...
|56
|55
|...
|0
|align="left"|(비트 인덱스)*
|-
|colspan="8"| * IBM 문서에서는 비트를 왼쪽에서 오른쪽으로 번호 매기며, 최상위 비트를 비트 번호 0으로 지정한다.
|}

이 형식의 지수는 해당 IEEE 이진 형식의 약 4분의 1 범위만 다룬다.

14개의 16진수 자릿수 정밀도는 대략 17개의 10진수 자릿수와 동일하다. 배정밀도 16진수 부동소수점을 10진수 문자열로 변환하고 다시 동일한 16진수 부동소수점 값으로 변환하려면 최소 18개의 유효 숫자가 필요하다.

 확장 정밀도 128비트 
IBM에서 확장 정밀도라고 부르는 4배 정밀도 HFP 형식은 System/370 시리즈에 추가되었고 일부 S/360 모델(S/360-85, -195 및 특별 요청 또는 OS 소프트웨어로 시뮬레이션된 다른 모델)에서 사용할 수 있었다. 확장 정밀도 분수 필드는 더 넓고, 확장 정밀도 숫자는 두 개의 더블 워드(16바이트)로 저장된다.

{|
|-
|colspan="8" |상위 부분
|- style="text-align:center"
|style="width:20px"|1
|style="width:20px"|
|style="width:50px"|7
|style="width:20px"|
|style="width:20px"|
|style="width:320px"|56
|style="width:20px"|
|style="text-align:left"|(비트 너비)
|- style="text-align:center"
|colspan="1" style="text-align:center;background-color:#FC9"|S
|colspan="3" style="text-align:center;background-color:#99F"|Exp
|colspan="3" style="text-align:center;background-color:#9F9"|Fraction (상위 14자리)
|colspan="1" style="text-align:center;background-color:#FFF"| 
|- style="text-align:center"
|127
|126
|...
|120
|119
|...
|64
|align="left"|(비트 인덱스)*
|-
|colspan="8" |하위 부분
|- style="text-align:center"
|colspan="4"|8
|
|56
|
|style="text-align:left"|(비트 너비)
|- style="text-align:center"
|colspan="4" style="text-align:center;background-color:#CCC"|미사용
|colspan="3" style="text-align:center;background-color:#9F9"|Fraction (하위 14자리)
|colspan="1" style="text-align:center;background-color:#FFF"| 
|- style="text-align:center"
|63
|colspan="2"|...
|56
|55
|...
|0
|align="left"|(비트 인덱스)*
|-
|colspan="8"| * IBM 문서에서는 비트를 왼쪽에서 오른쪽으로 번호 매기며, 최상위 비트를 비트 번호 0으로 지정한다.
|}

28개의 16진수 정밀도는 대략 32개의 10진수 정밀도와 동일하다. 확장 정밀도 HFP를 10진수 문자열로 변환하고 다시 동일한 HFP 값으로 변환하려면 최소 35개의 유효 숫자가 필요하다. 하위 부분에 저장된 지수는 상위 부분보다 14 작으며, 0보다 작아지는 경우는 제외된다.

 산술 연산 
사용 가능한 산술 연산은 정규화된 덧셈 및 뺄셈, 비정규화된 덧셈 및 뺄셈, 그리고 비교이다. 사전 정규화는 지수 차이를 기반으로 수행된다. 곱셈과 나눗셈은 비정규화된 값을 사전 정규화하고, 하나의 가드 숫자 뒤에 결과를 잘라낸다. 2로 나누는 것을 단순화하는 반분 연산이 있다. ESA/390부터는 제곱근 연산이 있다. 모든 연산은 정밀도 손실을 방지하기 위해 하나의 16진수 가드 숫자를 갖는다. 대부분의 산술 연산은 간단한 주머니 계산기처럼 잘라낸다. 따라서 1 − 16−8 = 1이다. 이 경우 결과는 0에서 멀어지는 방향으로 반올림된다.

 IBM 메인프레임의 IEEE 754 
1998년 S/390 G5부터 IBM 메인프레임은 IEEE 754 부동소수점 표준을 준수하는 IEEE 이진 부동소수점 장치도 포함하고 있다. IEEE 십진 부동소수점은 2007년 IBM System z9 GA2에 밀리코드를 사용하여 추가되었고, 2008년에는 IBM System z10에 하드웨어로 추가되었다.

현대 IBM 메인프레임은 3가지 16진수(HFP) 형식, 3가지 2진수(BFP) 형식, 3가지 10진수(DFP) 형식으로 세 가지 부동소수점 기수를 지원한다. 코어당 두 개의 부동소수점 장치가 있으며, 하나는 HFP 및 BFP를 지원하고 다른 하나는 DFP를 지원한다. 모든 3가지 형식을 담는 하나의 레지스터 파일, FPRs가 있다. 2015년 z13부터 프로세서에는 각각 128비트 너비의 32개 벡터 레지스터를 포함하는 벡터 기능이 추가되었다. 벡터 레지스터는 두 개의 64비트 또는 네 개의 32비트 부동소수점 숫자를 포함할 수 있다. 전통적인 16개의 부동소수점 레지스터는 새로운 벡터 레지스터 위에 겹쳐져 있으므로 일부 데이터는 전통적인 부동소수점 명령어 또는 새로운 벡터 명령어로 조작할 수 있다.

 특별한 용도 
IBM HFP 형식은 다음 용도로 사용된다.

 미국 식품의약국(FDA)이 신약 허가 신청(NDA) 연구 제출에 요구하는 SAS 5 전송 파일(.XPT)
 기상 예측 모델의 출력을 교환하기 위한 GRIB (GRIdded Binary) 데이터 파일 (현재 버전에서는 IEEE 단정밀도 부동소수점수)
 GDS II (Graphic Database System II) 형식 파일 (OASIS가 대체) 및
 SEG Y (Society of Exploration Geophysicists Y) 형식 파일 (IEEE 단정밀도 부동소수점은 2002년에 이 형식에 추가됨)

IBM이 HFP 형식을 사용하는 하드웨어의 유일한 공급업체이며, 이 형식을 지원하는 유일한 IBM 기계가 그들의 메인프레임이기 때문에, 이를 요구하는 파일 형식은 거의 없다. 한 가지 예외는 FDA가 요구하는 SAS 5 전송 파일 형식인데, 이 형식에서는 "파일의 모든 부동소수점 숫자는 IBM 메인프레임 표현을 사용하여 저장된다. [...] 대부분의 플랫폼은 부동소수점 숫자에 IEEE 표현을 사용한다. [...] 전송 파일을 읽고/쓰는 데 도움이 되도록, IEEE 표현(빅 엔디안 또는 리틀 엔디안 모두)에서 전송 표현으로 변환하고 다시 변환하는 루틴을 제공한다." IBM 형식의 코드는 LGPLv2.1 하에서도 이용 가능하다.

 IBM 부동소수점 형식을 사용하는 시스템 
 IBM 시스템/360 및 후속 기종
 RCA 스펙트라 70
 잉글리시 일렉트릭 시스템 4
 GEC 4000 시리즈 미니컴퓨터
 인터데이터 16비트 및 32비트 컴퓨터
 SDS 시그마 시리즈
 데이터 제너럴 미니컴퓨터
 ICL 2900 시리즈 컴퓨터
 지멘스 7.700 및 7.500 시리즈 메인프레임 및 후속 기종

 십육진 부동소수점의 동기 

"IBM 시스템/360 아키텍처"라는 기사는 "이 선택으로 인해 부동소수점 덧셈에서 사전 시프트, 오버플로, 정밀도 손실 후 시프트의 빈도가 상당히 감소하기 때문"이라고 선택 이유를 설명한다. 이는 대형 System/360 모델의 성능을 향상시키고 소형 모델의 비용을 절감했다. 저자들은 정밀도 손실 가능성을 알고 있었지만, 64비트 부동소수점 변수에는 중요하지 않을 것이라고 가정했다. 불행히도, 설계자들은 많은 숫자가 정밀도 감소를 겪게 될 것이라는 벤포드의 법칙을 알지 못했던 것 같다.

System/360의 두 설계자 중 한 명인 스위니의 1958-65년 연구에 따르면, 2보다 큰 밑을 사용하면 정렬 및 정규화에 필요한 시프트 수가 크게 줄어들며, 특히 필요한 다른 시프트의 수가 줄어든다고 인용한다. 그들은 구현 속도를 높이기 위해 더 큰 밑을 사용했으며, 8비트 바이트를 고려할 때 16진법이 자연스러운 선택이었다. 32비트 부동소수점은 반올림 오류를 전파하지 않는 계산에만 사용되고, 64비트 배정밀도는 모든 과학 및 공학 계산에 사용될 예정이었다. 초기 배정밀도 구현에는 적절한 반올림을 허용하는 가드 숫자가 없었지만, 이는 첫 고객 인도 직후 변경되었다.

 같이 보기 
 IEEE 754 부동소수점 표준
 마이크로소프트 이진 형식

 각주 

 더 읽어보기 


 Harding, L. J. (1966), "Idiosyncrasies of System/360 Floating-Point", Proceedings of SHARE 27, August 8–12, 1966, Presented at SHARE XXVII, Toronto, Canada doi:10.5281/zenodo.10566524.
 Harding, L. J. (1966), "Modifications of System/360 Floating-Point", Proceedings of SHARE 27, August 8-12, 1966, Presented at SHARE XXVII, Toronto, Canada doi:10.5281/zenodo.10566780.
 Harding, L. J. (1966), "Proposed Modification Of Floating-Point Multiplication", proposed Engineering Change to IBM Corporation, doi:10.5281/zenodo.10567044.




분류:컴퓨터 산술
분류:부동소수점