Embedded C: Fake float

c
embedded

(Nguyễn đình Cuội) #1

Trong lập trình nhúng , cụ thể là automotive, có khi trong một cái sensor trên oto thì phần mềm điều khiển của nó chỉ đơn thuần là 1 chương trình C be bé, không sử dụng đến hệ điều hành. Khi thiết kế phần cứng người ta chọn những con chip …yếu xìu ( CPU max 64 Mhz, Ram chỉ vẻn vẹn vài KB :triumph:) và đưa ra những quy tắc viết code rất chặt chẽ. Một trong số đó là khi tính toán tất cả phải sử dụng kiểu dữ liệu nguyên (long, int , short , char ) và không được sử dụng kiểu float/double vì nó sẽ làm chậm hiệu năng của chương trình. Vấn đề nảy sinh từ đây.
Giả sử mình có bài toán thế này :
Tính giá trị điện áp ( Result ) dựa vào giá trị AD theo biểu thức :

Result = ( AD – OFFSET ) * Ratio * Correction
Ratio = 1.15556 ; Correction = 0.950 , OFFSET = 128
Hay Result = ( AD – 128 ) * 1.15556*0.95

Trên những hệ thống Desktop computer với những Intel core I hay AMD ryzen hùng mạnh thì chỉ cần đơn giản làm 1 hàm :

double calculate( unsigned char AD ) 
{

	double Result = ( AD – 128 ) * 1.15556*0.95;
        return Result; 
}

Tuy nhiên với một yêu cầu …quá đáng là không được sử dụng double/float thì chỗ này phải làm như nào ? May mắn ở đây là các giá trị cần biểu diễn bằng float đều là hằng số ( Ratio và Correction) nên ta có thể sử dụng một phương pháp gọi là fake float.
Ý tưởng của phương pháp này là dùng phân số để biểu diễn số thực, ví dụ

1.5 = 3/2
0.333333 = 1/3
0.25 = 1/4

Do đó ta có thể tính :

0.95 = 95/100
1.15556 = 115556/100000

Bây giờ giả sử AD = 228 cho đơn giản, khi tính bằng double :

Result = 100 * 0.95* 1.15556 = 109.7782

Còn tính bằng int :

Result = 100 * 95 * 115556 / 100000 / 100 = 109

Làm như trên ta có sai số là 0.7782 ( tầm 0.7% ), tạm chấp nhận được. Nếu muốn làm giảm sai số ta cần biểu diễn chi tiết hơn nữa. Còn nếu giá trị float kia là biến thì độ phức tạp sẽ còn tăng thêm :joy:

Cuối cùng code trở thành

unsigned int calculate( unsigned char AD ) {

	unsigned int Result = ( AD – 128 ) * 115556*95/100000/100;

        return Result; 
}

Bạn nào quan tâm có thể tìm hiểu thêm trong cuốn Making embedded systems :grin:


(Quốc Hưng Hoàng) #2

Cho mình hỏi cuốn Making embedded system có phần bài tập thực hành với các kit như PIC, STM không bạn ? :smiley:


(Văn Dương) #3

Tính toán với float tuy có thọt hiệu năng so với int. Nhưng làm gì đến mức gây ra vấn đề hoặc không được dùng mà phải khổ thế kia.

Kiểu phân số cũng phải nâng số bit dữ liệu nên cũng hoà cả làng thôi.
Ví dụ 0.99567= 99567 / 100000 thì phải 2 số int 32 bit hoặc nhọ hơn phải nâng lên 2 số 64 bit mới lưu nổi tử mẫu và chống tràn số. Con chip 8,16 bit cũng è cổ khi tính toán với int32, int64
Số float hay double cũng chưa chắc giống nhau giữa trình biên dịch nhúng và trình biên dịch App cho máy tính.


83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?