Xác định trường hợp đối số vệt phẩy hễ đã chỉ ra rằng bình thường, có nghĩa là không buộc phải là 0, hàm dưới, vô hạn, cũng chưa phải NaN.Bạn sẽ xem: Floating point number là gì

Một số bởi 0, vô hạn hoặc NaN là rõ ràng chân thành và ý nghĩa của nó. Nhưng mà nó cũng cho biết điều huyền bí. Bao giờ một số là ẩn số?

công dụng đầu tiên của google cho biết thêm nó chỉ là một trong những từ đồng nghĩa tương quan với một từ không bình thường: en.wikipedia.org/wiki/Denormal_number Xem câu hỏi này để thảo luận chuyên sâu về các mệnh giá chỉ và xử trí chúng: stackoverflow.com/questions/9314534/…

Trong tiêu chuẩn IEEE754, số lốt phẩy rượu cồn được màn biểu diễn dưới dạng ký kết hiệu công nghệ nhị phân, x = M × 2 e . Ở phía trên M là phần định trị với esố mũ . Về mặt toán học, các bạn luôn hoàn toàn có thể chọn số mũ sao cho một ≤ M e phút . Những con số này là hầu hết subnormals hoặc denormals .Bạn đã xem: Floating point number là gì

Trên thực tế, phần định trị được lưu trữ mà không tồn tại số 1 đứng đầu, vì luôn có số 1 đứng đầu, ngoại trừ các số rất thường (và số 0). Vày đó, cách phân tích và lý giải là giả dụ số nón không cực tiểu, thì có một số ẩn dẫn đầu là 1, và nếu số mũ là cực tiểu thì ko có, với số là hàm số phụ

*) bao quát hơn, 1 ≤ M

— Kerrek SB nguồn ai đang nói isnomallà truenếu 8 bit đều bởi 0 và falsengược lại? — Pacerier "được lưu giữ trữ" giỏi được diễn giải? — Pacerier Pacerier: "storage": Nó được lưu trữ mà không tồn tại số 1 nghỉ ngơi đầu, ví dụ như 001010, với được phát âm là 1.001010. — Kerrek SB, gồm rõ emin được nhắc trong: `` e min không? `` (Tôi hy vọng nỗ lực định dạng của mình thành công) .. — Razzle 82

Kiến thức cơ phiên bản về IEEE 754

Trước tiên, chúng ta hãy xem xét hầu hết điều cơ bạn dạng của IEEE 754 số được tổ chức.

Bạn đang xem: Floating point là gì

Chúng tôi sẽ triệu tập vào độ đúng chuẩn duy tuyệt nhất (32-bit), nhưng mọi thứ có thể được bao quát hóa ngay mau lẹ sang các phân khu vực khác.

Định dạng là:

1 bit: dấu8 bit: số mũ23 bit: phân số

Hoặc nếu mình muốn hình ảnh:


*

Nguồn .

Dấu hiệu rất 1-1 giản: 0 là tích cực và một là tiêu cực, xong câu chuyện.

Số mũ dài 8 bit và do đó nó nằm trong khoảng từ 0 đến 255.

Số mũ được gọi là chệch bởi vì nó bao gồm phần bù -127, ví dụ:

0 == special case: zero or subnormal, explained below 1 == 2 ^ -126 ...125 == 2 ^ -2126 == 2 ^ -1127 == 2 ^ 0128 == 2 ^ 1129 == 2 ^ 2 ...254 == 2 ^ 127255 == special case: infinity & NaNQuy cầu bit sản phẩm đầu

Trong khi xây dựng IEEE 754, những kỹ sư nhận thấy rằng tất cả các số, bên cạnh 0.0, đều phải sở hữu một 1số nhị phân là chữ số đầu tiên. Ví dụ:

25.0 == (binary) 11001 == 1.1001 * 2^4 0.625 == (binary) 0.101 == 1.01 * 2^-1cả nhị đều ban đầu với 1.phần khó tính đó .

Do đó, sẽ tương đối lãng phí nếu để chữ số đó chỉ chiếm một bit đúng mực gần như mỗi số.

Vì tại sao này, bọn họ đã tạo ra "quy cầu bit mặt hàng đầu":

luôn trả định rằng số bắt đầu bằng một

Nhưng sau đó làm thế nào để đối phó cùng với 0.0? Chà, họ đưa ra quyết định tạo một ngoại lệ:

nếu số mũ là 0và phân số là 0sau đó số đại diện cho cùng hoặc trừ 0.0

để những byte 00 00 00 00cũng thay mặt 0.0, trông đẹp.

Nếu chúng ta chỉ coi xét những quy tắc này, thì số không giống 0 nhỏ dại nhất rất có thể được màn biểu diễn sẽ là:

số mũ: 0phân số: 1

trông y hệt như thế này vào một phân số hex bởi vì quy mong bit sản phẩm đầu:

1.000002 * 2 ^ (-127)ở đâu .000002là 22 số 0 với một 1ở cuối.

Chúng tôi cấp thiết lấy fraction = 0, nếu không con số này sẽ là 0.0.

Nhưng rồi những kỹ sư, phần lớn người cũng có thể có óc thẩm mỹ và làm đẹp nhạy bén, vẫn nghĩ: điều đó không xấu sao? Rằng bọn họ nhảy từ thẳng 0.0đến một cái gì đấy thậm chí không phải là lũy thừa thích hợp của 2? bằng phương pháp nào đó chúng ta không thể đại diện thay mặt cho những con số thậm chí còn bé dại hơn?

Các số lượng bất thường

Các kỹ sư vò đầu bứt tai một lúc, với trở lại, như thường lệ, cùng với một ý tưởng phát minh hay khác. Điều gì sẽ xảy ra nếu cửa hàng chúng tôi tạo một luật lệ mới:

Nếu số nón là 0, thì:

bit trước tiên trở thành 0số mũ được sửa thành -126 (không bắt buộc -127 như thể chúng ta không có ngoại lệ này)

Những con số như vậy được hotline là số hết sức thường (hoặc số không bình thường là từ bỏ đồng nghĩa).

Quy tắc này ngay lập tức lập tức ngụ ý rằng số lượng như vậy:

số mũ: 0phân số: 0

vẫn còn 0.0, đó là 1 trong những loại thanh lịch vày nó tức là một quy tắc ít hơn để theo dõi.

Vì vậy, 0.0thực sự là một số trong những siêu thường xuyên theo tư tưởng của chúng tôi!

Khi đó, với quy tắc mới này, số ko chuẩn bé dại nhất là:

số mũ: 1 (0 đang là ẩn số)phân số: 0

đại diện:

1.0 * 2 ^ (-126)Khi đó, số bậc ba lớn số 1 là:

số mũ: 0phân số: 0x7FFFFF (23 bit 1)

bằng:

0.FFFFFE * 2 ^ (-126)nơi .FFFFFEmột đợt nữa 23 bit một bên cần dấu chấm.

Con số này khá gần với con số không bình thường bé dại nhất, nghe có vẻ lành mạnh.

Và số phụ nhỏ tuổi nhất không giống 0 là:

số mũ: 0phân số: 1

bằng:

0.000002 * 2 ^ (-126)trông cũng khá gần với 0.0!

Như chúng ta có thể thấy, những số siêu thông thường có sự cân bằng giữa độ đúng chuẩn và độ nhiều năm biểu diễn.

Như ví dụ cực đoan nhất, hàm phụ nhỏ nhất khác 0:

0.000002 * 2 ^ (-126)về cơ bạn dạng có độ đúng đắn của một bit thay do 32 bit. Ví dụ, nếu bọn họ chia nó cho hai:

0.000002 * 2 ^ (-126) / 2chúng tôi đích thực tiếp cận 0.0chính xác!

Hình dung

Luôn vẫn là một ý tưởng tuyệt khi bao gồm trực giác hình học về mọi gì bọn họ học được, vày vậy hãy tiếp tục.

Nếu chúng ta vẽ biểu đồ dùng IEEE 754 số dấu phẩy hễ trên một dòng cho từng số mũ sẽ cho, nó trông giống hệt như sau:

+---+-------+---------------+-------------------------------+exponent |126| 127 | 128 | 129 | +---+-------+---------------+-------------------------------+ | | | | | v v v v v -------------------------------------------------------------floats ***** * * * * * * * * * * * * ------------------------------------------------------------- ^ ^ ^ ^ ^ | | | | | 0.5 1.0 2.0 4.0 8.0Từ đó chúng ta cũng có thể thấy rằng:

đối với từng số mũ, không tồn tại sự chồng chéo giữa những số được biểu diễnvới mỗi số mũ, chúng ta có cùng một số trong những 2 ^ 32 trong số các số (ở phía trên được biểu thị bằng 4 *)trong mỗi số mũ, những điểm giải pháp đều nhausố mũ mập hơn bao hàm các phạm vi bự hơn, nhưng với các điểm trải rộng hơn

Bây giờ, hãy gửi nó xuống hết số nón 0.

Nếu không có subnormals, theo giả thuyết, nó sẽ giống hệt như sau:

+---+---+-------+---------------+-------------------------------+exponent | ? | 0 | 1 | 2 | 3 | +---+---+-------+---------------+-------------------------------+ | | | | | | v v v v v v -----------------------------------------------------------------floats * **** * * * * * * * * * * * * ----------------------------------------------------------------- ^ ^ ^ ^ ^ ^ | | | | | | 0 | 2^-126 2^-125 2^-124 2^-123 | 2^-127Với subnormals, nó trông như thế này:

+-------+-------+---------------+-------------------------------+exponent | 0 | 1 | 2 | 3 | +-------+-------+---------------+-------------------------------+ | | | | | v v v v v -----------------------------------------------------------------floats * * * * * * * * * * * * * * * * * ----------------------------------------------------------------- ^ ^ ^ ^ ^ ^ | | | | | | 0 | 2^-126 2^-125 2^-124 2^-123 | 2^-127Bằng cách so sánh hai biểu đồ, công ty chúng tôi thấy rằng:

phạm vi >= 23; float32.exponent = bytes & 0x000000FF; bytes >>= 8; float32.sign = bytes & 0x000000001; bytes >>= 1; return float32;}float float_from_bytes( uint32_t sign, uint32_t exponent, uint32_t fraction) = exponent; bytes 23; bytes int float32_equal( float f, uint32_t sign, uint32_t exponent, uint32_t fraction) Float32 float32; float32 = float32_from_float(f); return (float32.sign == sign) && (float32.exponent == exponent) && (float32.fraction == fraction) ;void float32_print(float f) Float32 float32 = float32_from_float(f); printf( "%" PRIu32 " %" PRIu32 " %" PRIu32 " ", float32.sign, float32.exponent, float32.fraction );int main(void) /* Basic examples. */ assert(float32_equal(0.5f, 0, 126, 0)); assert(float32_equal(1.0f, 0, 127, 0)); assert(float32_equal(2.0f, 0, 128, 0)); assert(isnormal(0.5f)); assert(isnormal(1.0f)); assert(isnormal(2.0f)); /* Quick nhận xét of C hex floating point literals. */ assert(0.5f == 0x1.0p-1f); assert(1.0f == 0x1.0p0f); assert(2.0f == 0x1.0p1f); /* Sign bit. */ assert(float32_equal(-0.5f, 1, 126, 0)); assert(float32_equal(-1.0f, 1, 127, 0)); assert(float32_equal(-2.0f, 1, 128, 0)); assert(isnormal(-0.5f)); assert(isnormal(-1.0f)); assert(isnormal(-2.0f)); /* The special case of 0.0 và -0.0. */ assert(float32_equal( 0.0f, 0, 0, 0)); assert(float32_equal(-0.0f, 1, 0, 0)); assert(!isnormal( 0.0f)); assert(!isnormal(-0.0f)); assert(0.0f == -0.0f); /* ANSI C defines FLT_MIN as the smallest non-subnormal number. */ assert(FLT_MIN == 0x1.0p-126f); assert(float32_equal(FLT_MIN, 0, 1, 0)); assert(isnormal(FLT_MIN)); /* The largest subnormal number. */ float largest_subnormal = float_from_bytes(0, 0, 0x7FFFFF); assert(largest_subnormal == 0x0.FFFFFEp-126f); assert(largest_subnormal /* The smallest non-zero subnormal number. */ float smallest_subnormal = float_from_bytes(0, 0, 1); assert(smallest_subnormal == 0x0.000002p-126f); assert(0.0f return EXIT_SUCCESS;GitHub ngược dòng .

Biên dịch và chạy với:

gcc -ggdb3 -O0 -std=c11 -Wall -Wextra -Wpedantic -Werror -o subnormal.out subnormal.c./subnormal.outC ++

Ngoài bài toán hiển thị toàn bộ các API của C, C ++ cũng cho thấy một số tính năng phụ liên quan đến công dụng phụ không tồn tại sẵn trong C , ví dụ:

Trong C ++, toàn thể API được tạo khuôn mẫu đến từng các loại dấu phẩy hễ và trông đẹp hẳn nhiều.

Triển khai

x86_64 cùng ARMv8 tích hợp IEEE 754 trực tiếp bên trên phần cứng, mà lại mã C dịch sang.

Subnormals ngoài ra kém cấp tốc hơn bình thường trong các triển khai tốt nhất định: nguyên nhân việc thay đổi 0,1f thành 0 lại làm chậm công suất đi 10 lần? Điều này được kể trong sách gợi ý ARM, hãy coi phần "chi ngày tiết về ARMv8" của câu trả lời này.

Chi máu về ARMv8

Sách phía dẫn tìm hiểu thêm kiến ​​trúc ARM Sổ tay phía dẫn áp dụng ARMv8 DDI 0487C.a A1.5.4 "Flush-to-zero" miêu tả một chính sách có thể định thông số kỹ thuật trong đó những khẩu súng con được làm tròn thành 0 để nâng cấp hiệu suất:

Hiệu suất của quy trình xử lý vệt phẩy động rất có thể bị sút khi tiến hành các phép tính tương quan đến những số không chuẩn hóa với ngoại lệ dòng chảy dưới. Trong vô số thuật toán, năng suất này rất có thể được hồi phục mà không ảnh hưởng đáng nói đến độ đúng đắn của công dụng cuối cùng, bằng phương pháp thay thế các toán hạng không chuẩn chỉnh hóa và hiệu quả trung gian bằng các số không. Để được cho phép tối ưu hóa này, thực hiện dấu phẩy cồn ARM được cho phép sử dụng chính sách Flush-to-zero cho các định dạng vệt phẩy động khác nhau như sau:

Đối cùng với AArch64:

Nếu FPCR.FZ==1, thì chế độ Flush-to-Zero được thực hiện cho tất cả các đầu vào và đầu ra đúng mực đơn và đúng mực kép của toàn bộ các lệnh.

Nếu FPCR.FZ16==1, thì cơ chế Flush-to-Zero được thực hiện cho tất cả các nguồn vào và đầu ra output của Half-Precision của lệnh vệt phẩy động, ngoại trừ: —Chuyển thay đổi giữa số Half-Precision với Single-Precision. — biến hóa giữa Half-Precision cùng Double-Precision những nhỏ số.

A1.5.2 "Tiêu chuẩn dấu phẩy đụng và thuật ngữ" Bảng A1-3 "Thuật ngữ vệt phẩy động" xác thực rằng ký kết hiệu con và ký hiệu là tự đồng nghĩa:

This manual IEEE 754-2008------------------------- -------------Denormal, or denormalized SubnormalC5.2.7 "FPCR, Thanh ghi điều khiển và tinh chỉnh dấu chấm động" mô tả giải pháp ARMv8 rất có thể tùy chọn nâng cao các ngoại lệ hoặc đặt những bit cờ bất cứ bao giờ đầu vào của một phép toán vệt chấm động là không bình thường:

FPCR.IDE, bit Đầu vào Kích hoạt bả ngoại lệ lốt phẩy cồn bất thường. Giá chỉ trị rất có thể là:

0b0 Đã chọn cách xử lý ngoại lệ chưa được gói. Trường hợp ngoại lệ lốt chấm động xẩy ra thì bit FPSR.IDC được để thành 1.

0b1 Đã chọn cách xử lý ngoại lệ bị mắc kẹt. Nếu ngoại lệ vết phẩy hễ xảy ra, PE không update bit FPSR.IDC. Phần mềm xử lý bẫy hoàn toàn có thể quyết định gồm đặt bit FPSR.IDC thành 1 giỏi không.

D12.2.88 "MVFR1_EL1, AArch32 truyền thông and VFP Feature Register 1" cho thấy thêm rằng bên trên thực tế, cung ứng không thông thường là hoàn toàn tùy lựa chọn và hỗ trợ một chút nhằm phát hiện xem có cung ứng không:

FPFtZ, bit

Chuyển sang chế độ Zero. Cho thấy việc tiến hành dấu phẩy cồn chỉ cung ứng hỗ trợ cho chính sách hoạt hễ Flush-to-Zero. Giá bán trị khẳng định là:

0b0000 không được triển khai hoặc hartware chỉ hỗ trợ chính sách hoạt rượu cồn Flush-to-Zero.

0b0001 Phần cứng cung ứng số học tập không chuẩn chỉnh hóa đầy đủ.

Tất cả những giá trị không giống được bảo lưu.

Xem thêm: Phân Tích Tình Mẫu Tử Của Bà Cụ Tứ Và Người Đàn Bà Hàng Chài Ngắn Gọn

Điều này cho thấy thêm rằng khi các toán tử bé không được triển khai, những triển khai chỉ hoàn nguyên về 0.