1+ #include < iostream>
2+ #include < fstream>
3+ #include < cstdint>
4+ #include < cassert>
5+ #include < algorithm>
6+ #include < vector>
7+ #include < string>
8+
9+ // -------------------- 128 位分数类 --------------------
10+ struct Fraction {
11+ __int128 num; // 分子
12+ __int128 den; // 分母 (恒正)
13+
14+ Fraction (__int128 n = 0 , __int128 d = 1 ) : num(n), den(d) {
15+ if (den < 0 ) { num = -num; den = -den; }
16+ reduce ();
17+ }
18+
19+ // 约分
20+ void reduce () {
21+ if (den == 0 ) throw std::runtime_error (" Denominator zero" );
22+ __int128 g = gcd (num < 0 ? -num : num, den);
23+ num /= g;
24+ den /= g;
25+ }
26+
27+ static __int128 gcd (__int128 a, __int128 b) {
28+ while (b != 0 ) { __int128 t = b; b = a % b; a = t; }
29+ return a < 0 ? -a : a;
30+ }
31+
32+ // 比较运算符
33+ bool operator <(const Fraction& rhs) const {
34+ return num * rhs.den < rhs.num * den;
35+ }
36+ bool operator <=(const Fraction& rhs) const {
37+ return num * rhs.den <= rhs.num * den;
38+ }
39+ bool operator ==(const Fraction& rhs) const {
40+ return num == rhs.num && den == rhs.den ;
41+ }
42+ bool operator !=(const Fraction& rhs) const { return !(*this == rhs); }
43+ bool operator >(const Fraction& rhs) const { return rhs < *this ; }
44+ bool operator >=(const Fraction& rhs) const { return rhs <= *this ; }
45+
46+ // 算术运算
47+ Fraction operator +(const Fraction& rhs) const {
48+ return Fraction (num * rhs.den + rhs.num * den, den * rhs.den );
49+ }
50+ Fraction operator -(const Fraction& rhs) const {
51+ return Fraction (num * rhs.den - rhs.num * den, den * rhs.den );
52+ }
53+ Fraction operator *(const Fraction& rhs) const {
54+ return Fraction (num * rhs.num , den * rhs.den );
55+ }
56+ Fraction operator /(const Fraction& rhs) const {
57+ return Fraction (num * rhs.den , den * rhs.num );
58+ }
59+
60+ // 取整 (floor)
61+ __int128 floor () const {
62+ if (num >= 0 ) return num / den;
63+ else return (num - den + 1 ) / den;
64+ }
65+
66+ // 小数部分
67+ Fraction frac () const {
68+ return *this - Fraction (floor (), 1 );
69+ }
70+
71+ // 转换为 double (仅用于调试输出,算法中不使用)
72+ double toDouble () const {
73+ return (double )num / (double )den;
74+ }
75+ };
76+
77+ // 幂函数
78+ Fraction pow (int base, int exp) {
79+ if (exp == 0 ) return Fraction (1 );
80+ if (exp < 0 ) return Fraction (1 ) / pow (base, -exp);
81+ __int128 result = 1 ;
82+ for (int i = 0 ; i < exp; ++i) result *= base;
83+ return Fraction (result);
84+ }
85+
86+ // -------------------- FP16 解析 --------------------
87+ struct FP16Components {
88+ uint16_t bits;
89+ __int128 c; // 有效数字 (整数)
90+ int q; // 指数
91+ bool is_regular; // f != 0 (包括次正规数)
92+ bool is_irregular; // f == 0 且 e != 0 (2的幂)
93+ };
94+
95+ FP16Components f16_to_components (uint16_t bits) {
96+ int exp = (bits >> 10 ) & 0x1F ;
97+ int frac = bits & 0x3FF ;
98+
99+ if (exp == 0 && frac == 0 ) throw std::invalid_argument (" +0 excluded" );
100+ if (exp == 31 ) throw std::invalid_argument (" inf/NaN excluded" );
101+
102+ FP16Components comp;
103+ comp.bits = bits;
104+
105+ if (exp == 0 ) { // 次正规数
106+ comp.c = frac;
107+ comp.q = -24 ;
108+ comp.is_regular = true ;
109+ comp.is_irregular = false ;
110+ } else { // 常规数
111+ comp.c = 1024 + frac;
112+ comp.q = exp - 25 ;
113+ comp.is_regular = (frac != 0 );
114+ comp.is_irregular = (frac == 0 );
115+ }
116+ return comp;
117+ }
118+
119+ // -------------------- 计算 k (完全整数逻辑) --------------------
120+ int compute_k (int q, bool is_regular) {
121+ int k;
122+ if (is_regular){
123+ k = (q * 1233 ) >> 12 ;
124+ }else {
125+ k = ((q * 1233 ) - 512 ) >> 12 ;
126+ }
127+ return k;
128+ }
129+
130+ // -------------------- 算法1:计算 (d, k) --------------------
131+ std::pair<__int128, int > f16_to_decimal (uint16_t bits) {
132+ auto comp = f16_to_components (bits);
133+ __int128 c = comp.c ;
134+ int q = comp.q ;
135+ bool is_regular = comp.is_regular ;
136+ bool is_irregular = comp.is_irregular ;
137+
138+ int k = compute_k (q, is_regular);
139+
140+ // v = c * 2^q
141+ Fraction v = Fraction (c) * pow (2 , q);
142+
143+ // R = v * 10^{-k-1}
144+ Fraction R = v * pow (10 , -k-1 );
145+ __int128 m = R.floor ();
146+ Fraction n = R.frac ();
147+
148+ __int128 ten = 10 * m;
149+
150+ // 10n = 10 * (R - m) = 10*R - 10*m
151+ Fraction tenR = v * pow (10 , -k); // v * 10^{-k}
152+ Fraction ten_n = tenR - Fraction (ten);
153+ __int128 floor_ten_n = ten_n.floor ();
154+ Fraction delta = ten_n.frac ();
155+
156+ __int128 one;
157+
158+ // Step 11-21: 根据 δ 确定 one 初值
159+ if (delta == Fraction (1 , 2 )) {
160+ if (floor_ten_n % 2 == 0 )
161+ one = floor_ten_n;
162+ else
163+ one = floor_ten_n + 1 ;
164+ } else if (delta < Fraction (1 , 2 )) {
165+ one = floor_ten_n;
166+ } else {
167+ one = floor_ten_n + 1 ;
168+ }
169+
170+ // Step 22-28: irregular 的特殊处理
171+ if (is_irregular) {
172+ Fraction cond1_val = pow (2 , q-2 ) * pow (10 , -k);
173+ Fraction cond2_val = pow (2 , q-2 ) * pow (10 , -k-1 );
174+
175+ if (delta > cond1_val) {
176+ one = floor_ten_n + 1 ;
177+ }
178+ if (cond2_val >= n) {
179+ one = 0 ;
180+ }
181+ } else {
182+ // Step 30-35: regular 情况下的最短表示检查
183+ Fraction A = pow (2 , q-1 ) * pow (10 , -k-1 );
184+
185+ if (A > n || (A == n && c % 2 == 0 )) {
186+ one = 0 ;
187+ } else if (A > (Fraction (1 ) - n) || (A == (Fraction (1 ) - n) && c % 2 == 0 )) {
188+ one = 10 ;
189+ }
190+ }
191+
192+ __int128 d = ten + one;
193+ return {d, k};
194+ }
195+
196+ // -------------------- 主程序 --------------------
197+ int main () {
198+ std::ofstream out (" f16_decimal_results.txt" );
199+ if (!out) {
200+ std::cerr << " Cannot open output file." << std::endl;
201+ return 1 ;
202+ }
203+
204+ out << " # bits(hex) d k\n " ;
205+
206+ // 遍历所有正 FP16 数值 (排除 0x0000, 0x7C00..0x7FFF)
207+ for (uint32_t bits = 0x0001 ; bits <= 0x7BFF ; ++bits) {
208+ try {
209+ auto [d, k] = f16_to_decimal (static_cast <uint16_t >(bits));
210+ out << " 0x" << std::hex << std::uppercase << bits << std::dec
211+ << " " << (int64_t )d << " " << k << " \n " ;
212+ } catch (const std::invalid_argument&) {
213+ // 跳过 +0, inf, NaN
214+ continue ;
215+ } catch (const std::exception& e) {
216+ std::cerr << " Error processing 0x" << std::hex << bits << " : " << e.what () << std::endl;
217+ return 1 ;
218+ }
219+ }
220+
221+ out.close ();
222+ std::cout << " Results written to f16_decimal_results.txt" << std::endl;
223+ return 0 ;
224+ }
0 commit comments