Floating point: trường bit, lớp giá trị và sai số làm tròn
Tiên quyết
Sau bài này bạn sẽ
- Giải mã dấu, exponent và fraction của binary32
- Phân biệt normal, subnormal, zero, infinity và NaN
- Dự đoán một ca rounding và phân biệt raw decoder với FPU
Miền rộng hơn bằng cách lưu cả hệ số và số mũ
Fixed-point dùng một thang đo chung. Floating point lưu thêm số mũ để biểu diễn cả giá trị rất nhỏ lẫn rất lớn trong cùng định dạng.
Đổi lại, khoảng cách giữa hai số biểu diễn kề nhau không cố định. Một phép tính ra số toán học hợp lệ vẫn có thể cần làm tròn. Nhiều bit hơn thường giảm sai số, nhưng không biến tính toán hữu hạn thành số thực chính xác.
Ba trường của số float 32 bit
Bài này dùng định dạng IEEE 754 binary32: một bit dấu s, tám bit exponent E và 23 bit fraction f. E là số nguyên lưu trong trường exponent, không phải số mũ đã bỏ bias.
| Trường | Số bit | Ý nghĩa trong số normal |
|---|---|---|
| s | 1 | Dấu của giá trị |
| E | 8 | Số mũ được mã hóa với bias 127 |
| f | 23 | Phần sau dấu chấm của significand có bit 1 dẫn ẩn |
Với 1 ≤ E ≤ 254, giá trị là (-1)^s × (1 + f/2^23) × 2^(E-127). “Bit 1 ẩn” chỉ áp dụng cho số normal, không áp dụng cùng cách cho subnormal hay zero.
Ví dụ +1 có s bằng 0, E bằng 127 và f bằng 0, nên raw hex là 3F80_0000. Với −2.5: độ lớn là 1.01 × 2^1, nên s bằng 1, E bằng 128 và f biểu diễn phần .01; raw là C020_0000.
Exponent biên dành cho các lớp đặc biệt
| E | f | Lớp | Cách đọc |
|---|---|---|---|
| 0 | 0 | ±0 | Dấu vẫn được lưu |
| 0 | khác 0 | Subnormal | (-1)^s × (f/2^23) × 2^(-126) |
| 1 .. 254 | bất kỳ | Normal | Dùng công thức có bit 1 dẫn ẩn |
| 255 | 0 | ±infinity | Không phải giá trị hữu hạn lớn nhất |
| 255 | khác 0 | NaN | Mã cho kết quả/đối tượng không phải số thông thường |
Subnormal dương nhỏ nhất là 2^(-149); normal dương nhỏ nhất là 2^(-126). Giá trị hữu hạn dương lớn nhất là (2-2^(-23)) × 2^127.
+0 và −0 có bit khác nhau, dù so sánh số học bằng nhau theo quy tắc thông thường. NaN cần cách xử lý riêng; kiểm bằng raw bit, so sánh số học và phân loại là ba tác vụ khác nhau. Ví dụ của bài chỉ phân lớp raw, chưa kiểm quiet/signaling NaN hay các cờ exception.
Đọc vài từ dữ liệu trước khi dùng phép tính
| Raw hex | Cách giải mã |
|---|---|
0000_0000 |
+0 |
8000_0000 |
−0 |
0000_0001 |
Subnormal dương nhỏ nhất |
007F_FFFF |
Subnormal dương lớn nhất |
3F80_0000 |
+1 |
C020_0000 |
−2.5 |
7F80_0000 |
+infinity |
FF80_0000 |
−infinity |
7FC0_0001 |
Một mã NaN |
Một vector HDL 32 bit chứa 3F80_0000 không tự biến thành số float +1. Đọc nó như unsigned integer sẽ cho một giá trị nguyên khác. Muốn tính float cần phép chuyển/diễn giải và toán tử hoặc IP hỗ trợ đúng định dạng.
Tương tự, cast số nguyên 1 sang float khác với diễn giải lại 32 bit của integer 1 như raw float. Một bên đổi giá trị biểu diễn, bên kia giữ bit và đổi cách đọc.
Khoảng cách và ties-to-even
Trong miền từ 1 tới trước 2 của binary32, hai số normal kề nhau cách 2^(-23). Chính giữa 1 và số kế tiếp là 1 + 2^(-24).
Bảng minh họa chính sách round-to-nearest, ties-to-even: chọn số gần nhất; nếu đúng giữa hai số, chọn significand có bit thấp nhất chẵn.
| Giá trị toán học | Kết quả binary32 theo chính sách đã nêu |
|---|---|
1 + 2^(-25) |
1, vì chưa tới điểm giữa |
1 + 2^(-24) |
1, vì đúng giữa và phía 1 có bit cuối chẵn |
1 + 3×2^(-24) |
1 + 2^(-22), phía trên có bit cuối chẵn |
Đây là một chính sách làm tròn, không phải mọi chế độ. Thứ tự tính còn có thể ảnh hưởng kết quả: sau mỗi bước làm tròn, thông tin đã mất chưa chắc khôi phục được. Đừng tự đổi ngoặc hoặc giả định tính kết hợp của phép cộng số thực luôn đúng cho float.
Chọn độ chính xác theo yêu cầu
binary32 có 24 bit significand hiệu dụng ở số normal, tính cả bit dẫn ẩn. binary64 có một bit dấu, 11 bit exponent, 52 bit fraction và bias 1023; số normal có 53 bit significand.
Thông số “khoảng 7 chữ số decimal” cho định dạng nhỏ chỉ là trực giác về độ chính xác, không phải bảo đảm mọi chuỗi 7 chữ số đều xử lý chính xác trong mọi phép toán. Nhiều phân số như 0.1 không có biểu diễn binary hữu hạn.
Trong thiết kế bộ xử lý tín hiệu hay FPU, cần chốt định dạng, chế độ rounding, xử lý subnormal, NaN/infinity, exception và latency. Một decoder trường bit không xác nhận được toàn bộ các yêu cầu đó.
Các lỗi đọc float thường gặp
- Dùng E trực tiếp làm số mũ mà quên trừ bias.
- Áp dụng bit 1 ẩn cho mọi E, kể cả zero/subnormal.
- Coi infinity là số hữu hạn lớn nhất.
- So byte raw rồi kết luận đã so giá trị số học.
- Nghĩ mọi phép tính decimal chính xác vì đầu ra hiển thị ít chữ số.
- Dùng kết quả trên máy host để khẳng định một FPU RTL chưa được kiểm.
Trong debug, in cả raw hex lẫn cách phân loại. Sau đó mới xem phép tính, rounding và thứ tự thao tác theo yêu cầu của khối.
Giải mã và tìm chỗ mất chính xác
- Giải mã
4000_0000bằng công thức số normal. - Vì sao E bằng 0, f bằng 0 không biểu diễn
1 × 2^(-127)? - So sánh raw +0 với −0; phép so bit khác phép so số học ở đâu?
- Nếu bỏ qua subnormal bằng cách đưa mọi E bằng 0 về zero, đã thay đổi những giá trị nào?
- Tại sao bước lượng tử quanh một triệu lớn hơn bước quanh 1 trong cùng định dạng?
Kiểm tra
Bằng chứng kiểm chứng
Expected tính trước chạy: FLOAT FORMAT CHECK cases=10 zero=2 subnormal=2 normal=2 infinity=2 nan=2 negative_mask=162 time_ns=10.
Mười raw word được chọn trước, hai mẫu mỗi lớp. Bảng lớp và bit dấu mong đợi độc lập với điều kiện phân loại. Parser và simulation đạt. Đây là decoder bit trong testbench, không phải FPU, không có claim synthesis, native float arithmetic hay IEEE conformance.
Thí nghiệm host riêng ở toolcheck/probes/a1_float_rounding.cpp đã kiểm ba kết quả bảng rounding bằng bit raw, xác nhận môi trường float 4 byte, significand 24 bit, IEC 559 và FE_TONEAREST. Biên dịch C++20 với -fno-fast-math -frounding-math -ffp-contract=off; kết quả: HOST ROUND CHECK cases=3 half=3f800000 odd_tie=3f800002 quarter=3f800000 negative_zero=80000000.
Bằng chứng host chỉ áp dụng cho môi trường đã chạy, tách khỏi claim của ví dụ SystemVerilog. Quy tắc IEEE đầy đủ vẫn giữ nhãn chờ đối chiếu.
Nguồn và mức độ đối chiếu
- IEEE 754-2019 floating-point arithmetic — chờ đối chiếu, Binary interchange formats, normal/subnormal, special values and roundTiesToEven — chưa đối chiếu chuẩn. Chưa đối chiếu với văn bản nguồn (chưa mở).
- Floating Point Numbers — bản chụp resources.zip, What is a Floating Point Number?; IEEE 754 Standard; Single-Precision Representation (32-bit); Double-Precision Representation (64-bit); Special Values in IEEE 754. Trích dẫn; nguồn đã đọc các mục liên quan.
- Thí nghiệm nguyên bản A1.float, Ten raw binary32 class/sign cases and separate host ties-to-even checks. Trích dẫn; nguồn đã đọc toàn văn.
- IEEE 1800-2023 SystemVerilog LRM, Packed bit selections and raw field classification — chưa đối chiếu LRM. Chưa đối chiếu với văn bản nguồn (chưa mở).
- IEEE 1800-2023 SystemVerilog LRM, Packed bit-field extraction and integral comparisons — chưa đối chiếu LRM. Chưa đối chiếu với văn bản nguồn (chưa mở).