Định dạng dấu phẩy động độ chính xác đơn

**Định dạng dấu phẩy động độ chính xác đơn** (đôi khi còn gọi là **FP32** hoặc **float32**) là một định dạng số máy tính, thường chiếm 32 bit trong bộ nhớ máy tính; nó có khả năng biểu diễn một dải động rộng các giá trị số bằng cách sử dụng dấu phẩy cơ số động.

Một biến số thực dấu phẩy động có khả năng biểu diễn một khoảng giá trị lớn hơn so với một biến dấu phẩy tĩnh có cùng kích thước bit at the cost of precision. Một biến số nguyên có dấu với kích thước 32 bit có thể nhận giá trị tối đa là 231 − 1 = 2.147.483.647, trong khi một biến dấu phẩy động cơ số 2 theo chuẩn IEEE 754 với kích thước 32 bit có thể nhận giá trị tối đa lên tới (2 − 2−23) × 2127 ≈ 3,4028235 × 1038. Tất cả các số nguyên có từ 7 chữ số thập phân trở xuống, và bất cứ giá trị 2*n* nào với điều kiện −149 ≤ *n* ≤ 127, đều có thể được chuyển đổi chính xác thành giá trị dấu phẩy động chính xác đơn theo chuẩn IEEE 754.

Theo tiêu chuẩn IEEE 754-2008, định dạng 32-bit cơ số 2 có tên chính thức là **binary32**; nó từng có tên gọi **single** trong chuẩn IEEE 754-1985. Ngoài ra IEEE 754 còn quy định về các kiểu số thực dấu phẩy động khác, như định dạng *[[Định dạng dấu phẩy động độ chính xác kép|chính xác kép]]* 64-bit cơ số 2, và gần đây hơn là các dạng biểu diễn bằng hệ 10.

Một trong những ngôn ngữ lập trình đầu tiên cung cấp các kiểu dữ liệu dấu phẩy động độ chính xác đơn và kép là Fortran. Trước khi IEEE 754-1985 được chấp thuận rộng rãi, cách biểu diễn và các thuộc tính của các kiểu dữ liệu dấu phẩy động đều phụ thuộc vào từng nhà sản xuất máy tính, từng mẫu máy tính và quyết định của các nhà thiết kế ngôn ngữ lập trình. Ví dụ, trong GW-BASIC, kiểu dữ liệu chính xác đơn được sử dụng là định dạng dấu phẩy động MBF 32-bit.

Định dạng chính xác đơn được gọi là *REAL* trong Fortran, *SINGLE-FLOAT* in Common Lisp, *float* trong C, C++, C#, Java, *Float* trong Haskell và Swift, và *Single* trong Object Pascal (Delphi), Visual Basic, và MATLAB. Tuy nhiên, các kiểu *float* trong Python, Ruby, PHP và OCaml cùng với *single* trong các phiên bản Octave trước 3.2 lại chỉ các số độ chính xác kép. Hầu hết các bản triển khai PostScript và một số hệ thống nhúng chỉ hỗ trợ định dạng chính xác đơn.

## Tiêu chuẩn IEEE 754: binary32
Tiêu chuẩn IEEE 754 quy định một giá trị *binary32* bao gồm:
* Bit dấu: 1 bit
* Kích thước mũ: 8 bit
* Độ chính xác định trị: 24 bit (chỉ có 23 bit được lưu tường minh)

Định dạng này cho độ chính xác từ 6 đến 9 chữ số thập phân có nghĩa. Nếu một xâu thập phân có từ dưới 6 chữ số có nghĩa được chuyển đổi sang dạng biểu diễn chính xác đơn IEEE 754, sau đó được chuyển đổi lại thành một xâu thập phân có cùng số chữ số như ban đầu, kết quả sẽ giống hệt như xâu gốc.

Bit dấu quyết định dấu của giá trị số và cả dấu của phần định trị. Phần mũ là một giá trị nguyên 8 bit không dấu từ 0 đến 255, được lưu dưới dạng có độ lệch (*[[:en:Exponent bias|biased exponent]]*): nếu phần mũ được lưu có giá trị là 127 thì giá trị thực sự phải là 0. Giá trị thực của phần mũ chỉ nằm trong khoảng từ −126 tới +127 bởi các giá trị mũ −127 (toàn 0) và +128 (toàn 1) được dành cho các số đặc biệt.

Phần định trị thực bao gồm 23 bit biểu diễn phần lẻ nằm ở phía bên phải dấu phẩy nhị phân cộng thêm một *bit hiểu ngầm* (nằm bên trái dấu phẩy nhị phân) có giá trị 1, trừ khi tất cả bit ở phần mũ đều là 0. Do đó chỉ có 23 bit phần lẻ của định trị xuất hiện trong định dạng bộ nhớ, còn tổng độ chính xác phải là 24 bit (tương đương với log10(224) ≈ 7,225 chữ số thập phân). Các bit được sắp xếp như sau:

* *sign*: bit dấu
* *exponent*: phần mũ 
* *fraction*: phần lẻ

Giá trị thực của một dữ liệu *binary32* 32 bit, có *dấu*, phần mũ lệch *e* (dạng số nguyên không dấu 8 bit) và *phần lẻ 23 bit* cho trước có thể được tính như sau
: (-1)^{b_{31}} \times 2^{(b_{30}b_{29} \dots b_{23})_2 - 127} \times (1.b_{22}b_{21} \dots b_0)_2,
tương đương với
: \text{giá trị} = (-1)^\text{dấu} \times 2^{(E-127)} \times \left(1 + \sum_{i=1}^{23} b_{23-i} 2^{-i} \right).

Trong ví dụ này:
* \text{dấu} = b_{31} = 0,
* (-1)^\text{dấu} = (-1)^{0} = +1 \in \{-1, +1\},
* E = b_{30}b_{29} \dots b_{23} = \sum_{i=0}^{7} b_{23+i} 2^{+i} = 124 \in \{1, \ldots, (2^8 - 1) - 1\} = \{1, \ldots, 254 \},
* 2^{(E-127)} = 2^{124-127} = 2^{-3} \in \{2^{-126}, \ldots, 2^{127}\} ,
* 1.b_{22}b_{21}...b_{0} = 1 + \sum_{i=1}^{23} b_{23-i} 2^{-i} = 1 + 1\cdot 2^{-2} = 1,25
\in \{1, 1+2^{-23}, \ldots, 2-2^{-23}\}
  \subset [1; 2 - 2^{-23}]
  \subset [1; 2).
do đó:
* \text{giá trị} = (+1) \times 2^{-3} \times 1.25 = +0,15625.

Lưu ý:
* 1+2^{-23} \approx 1,000\,000\,119,
* 2-2^{-23} \approx 1,999\,999\,881,
* 2^{-126}  \approx 1,175\,494\,35 \times 10^{-38},
* 2^{+127}  \approx 1,701\,411\,83 \times 10^{+38}.

### Mã hóa phần mũ
Phần mũ trong định dạng dấu phẩy động nhị phân độ chính xác đơn được mã hóa bằng cách biểu diễn offset-binary, với giá trị zero offset là 127; hay còn gọi là độ lệch mũ (*exponent bias*) trong chuẩn IEEE 754.
* Emin = 01H−7FH = −126
* Emax = FEH−7FH = 127
* Độ lệch mũ = 7FH = 127

Do đó, để lấy được giá trị thực của phần mũ thông qua cách biểu diễn offset-binary, cần phải trừ giá trị offset 127 khỏi phần mũ được lưu.

Các trường hợp phần mũ lưu với giá trị 00H và FFH là các trường hợp đặc biệt.

Giá trị chuẩn hóa dương nhỏ nhất là 2^{-126} \approx 1,18 \times 10^{-38} và giá trị dương nhỏ nhất (dưới mức chuẩn hóa) là 2^{-149} \approx 1,4 \times 10^{-45}.

### Giới hạn chính xác với các giá trị thập phân (từ 1 tới 16777216)
* Các số thập phân từ 1 tới 2: khoảng cố định 2−23 (1+2−23 là số dấu phẩy động lớn nhất tiếp theo sau 1)
* Các số thập phân từ 2 tới 4: khoảng cố định 2−22
* Các số thập phân từ 4 tới 8: khoảng cố định 2−21
* ...
* Các số thập phân từ 2n tới 2n+1: khoảng cố định 2n-23
* ...
* Các số thập phân từ 222=4194304 tới 223=8388608: khoảng cố định 2−1=0.5
* Các số thập phân từ 223=8388608 tới 224=16777216: khoảng cố định 20=1

### Giới hạn chính xác với các giá trị nguyên
* Các số nguyên từ 0 tới 16777216 có thể được biểu diễn chính xác (cũng áp dụng với các số nguyên âm từ −16777216 tới 0)
* Các số nguyên từ 224=16777216 tới 225=33554432 được làm tròn lên bội số của 2 (số chẵn)
* Các số nguyên từ 225 tới 226 được làm tròn lên bội số của 4
* ...
* Các số nguyên từ 2n tới 2n+1 được làm tròn lên bội số của 2n-23
* ...
* Các số nguyên từ 2127 tới 2128 được làm tròn lên bội số của 2104
* Các số nguyên bằng hoặc lớn hơn 2128 được làm tròn thành "vô cùng".

## Xem thêm
* Tiêu chuẩn IEEE về Số học Dấu phẩy động (IEEE 754)
* ISO/IEC 10967, số học độc lập ngôn ngữ
* Kiểu dữ liệu cơ bản

## Tham khảo

## Liên kết ngoài
* Trình chỉnh sửa mẫu bit dấu phẩy động trực tiếp
* Công cụ tính toán trực tuyến
* Trình chuyển đổi trực tuyến các số IEEE 754 có độ chính xác đơn
* Mã nguồn C chuyển đổi giữa các giá trị IEEE chính xác kép, đơn và bán chính xác