Thứ Sáu, 31 tháng 5, 2013

Các kiểu dữ liệu trong C

1. Kiểu số nguyên
Trong C chúng ta có một khai báo cho một biến kiểu nguyên như sau: int variable ;
Trong đó từ khóa int nói cho C biết biến được khai báo chứa một giá trị nguyên. Kiểu int thường chiếm 2 đến 4 bytes. Trên các máy UNIX, các số nguyên là các con số 32bits (4 bytes), cung cấp một dải giá trị đi từ -2147483648 đến 2147483648 (2 ^ 31 - 1). Trên PC, hầu hết compilers sử dụng chỉ 16 bits (2 bytes ), đi từ -32768 đến 32767 (2 ^ 15 - 1). Các kích thước này là đặc trưng cho từng môi trường. Bạn có thể tìm thấy trong header file limits.h các hằng số cho các giới hạn. Kích thước của của một số nguyên có dấu (signed int) hoặc số nguyên không dấu (unsigned int) là một kích thước chuẩn tùy thuộc vào từng kiểu máy cụ thể. Ví dụ, trên các hệ điều hành 16-bit, kiểu int  thường là 16 bits, hay là 2 bytes. Trong các hệ điều hành 32-bit, kiểu int thường là 32 bits, hoặc là 4 bytes. Do đó kiểu int là tương đương với hoặc là kiểu short int hoặc là kiểu long int, và unsigned int hoặc là tương đương với kiểu unsigned short hoặc kiểu unsigned long, phụ thuộc vào môi trường nhắm tới. Các kiểu int biểu diễn tất cả các giá trị có dấu nếu không có chỉ định gì thêm.

Các đặc tả int unsigned int (hay đơn giản là unsigned) định nghĩa các đặc tính nhất định của ngôn ngữ C (cho ví dụ, kiểu enum). Trong những trường hợp như vây, các định nghĩa của int  và unsigned int cho một triển khai cụ thể xác định lưu trữ thực sự.

Microsoft Specific
Các số nguyên có dấu được biểu diễn trong "two-complement form". Bit quan trọng nhất giữ dấu: 1 là số âm, 0 cho số dương và số 0.  

END Microsoft Specific

Note: 
Các đặc tả kiểu int và unsigned int được sử dụng rộng rãi trong các chương trình C bởi vì chúng cho phép một máy cụ thể xử lý các giá trị nguyên theo cách hiệu quả nhất dành cho máy đó. Tuy nhiên, do kích thước của kiểu int và unsigned int là khác nhau, các chương trình phụ thuộc vào kích thước kiểu cố định có thể không "portable" đến các máy khác. Để làm cho các chương trình nhiều portable, bạn có thể sử dụng expressions với sizeof operator thay cho việc sử dụng hard-coded data sizes.

2. Kiểu số thực (float)

Các số thực sử dụng định dạng IEEE (Institue of Eletrical and Eletronics Engineers). Các giá trị với độ chính xác đơn (single-precison values) với kiểu float có 4 bytes, bao gồm một bit dấu (sign bit), 8-bit dành cho phần mũ, và 23 bit dành cho phần định trị. Phần định trị biểu diễn một số nằm giữa 1.0 và 2.0. Bởi vì bit thứ tự cao (high-order bit) của phần định trị luôn là 1, nó không được lưu trong số đó. Kiểu float có dải giá trị từ 3.4E-38 đến 3.4E+38.

Bạn có thể định nghĩa các biến (variables) như là float hoặc là double, điều đó còn tùy thuộc vào các nhu cầu của ứng dụng bạn tạo. Sự khác biệt chính yếu giữa hai kiểu này có ý nghĩa đối với những gì chúng có thể biểu diễn, lượng lưu trữ (storage) chúng yêu cầu, và dải giá trị của chúng. Dưới đây tôi sẽ trình bày sự khác nhau các yêu cầu quan trọng và yêu cầu lưu trữ.

Các kiểu số thực
Type               Các chữ số quan trọng                    Số bytes
float                         6-7                                            4
double                      15-16                                         8

Các biến thực được biểu diễn bởi một phần định trị, những gì chứa giá trị của số và một lũy thừa.

Bảng sau đây cho ta thấy số lượng bit được cấp phát đến phần định trị và phần lũy thừa của mỗi kiểu số thực. Bit quan trọng nhất trong cả float hay double đều là bit dấu. Cũng như trong kiểu số nguyên, số 1 biểu diễn số âm, số 0 là số âm.

Các độ dài của phần định trị và phần mũ

Type               Độ dài phần lũy thừa                    Độ dài phần định trị
float                         8 bits                                            23 bits
double                     11 bits                                           52 bits

Bởi vì các lũy thừa được lưu trong dạng không dấu, lũy thừa bị sai lệch một nửa giá trị có thể có của nó. Đối với kiểu float, sai lệch là 127; đối với kiểu double, nó là 1023. Bạn có thể tính toán giá trị lũy thừa thực sự bằng cách trừ giá trị lũy thừa cho giá trị sai lệch.

Phần định trị được lưu như một phần nhị phân (binary fraction) lớn hơn hoặc bằng 1 và nhỏ hơn 2. Đối với các kiểu float và double, còn có một bit 1 được dùng làm bit dấu (bit quan trọng nhất), vì vậy các phần định trị thực sự dài 24 và và 53 bits, mặc dù bit quan trọng nhất không bao giờ được lưu trong bộ nhớ.

Thay cho phương thức lưu trữ vừa được mô tả, các gói số thực (floating-point package) có thể lưu có số thực nhị phân (binary floating-point numbers) như các số không bình thường. Các số không bình thường là các số thực khác không với các giá trị lũy thừa lưu trữ trong những gì mà bit quan trọng nhất của phần định trị bằng 0. Bởi việc sử dụng định dạng không bình thường, dải giá trị của số thực có thể được mở rộng theo mức chính xác nhất. Bạn không thể điều khiển được số thực được biểu diễn theo dạng bình thường hay là không bình thường; các gói số thực quyết định việc biểu diễn này. Các gói số thực không bao giờ sử dụng dạng không bình thường nếu lũy thừa không trở nên nhỏ hơn giá trị nhỏ nhất có thể biểu diễn trong dạng bình thường.

Bảng sau đây hiển thị các giá trị nhỏ nhất và lớn nhất bạn có thể lưu một biến trong mỗi kiểu thực. Các giá trị được liệt kê trong bảng này áp dụng cho các số thực bình thường; dạng không bình thường có giá trị nhỏ nhất bé hơn. Chú ý rằng, các số được lưu trữ trong các thanh ghi 80x87 thường được biểu diễn trong dạng bình thường 80-bit; các số chỉ có thể được biểu diễn trong dạng không bình thường khi được lưu trong các biến thực 32-bit và 64-bit (các biến cho kiểu float và long)

Dải giá trị của các kiểu thực

Type                        Giá trị nhỏ nhất                     Giá trị lớn nhất
float                         1.175494351 E – 38                     3.402823466 E + 38                       
double                     2.2250738585072014 E – 308         1.7976931348623158 E + 308                                 

Nếu sự chính xác là ít lo ngại hơn việc lưu trữ, hãy dùng kiểu float. Ngược lại, nếu độ chính xác là một tiêu chí hàng đầu, sử dụng kiểu double.

Các biến thực có thể được thúc đẩy đến một kiểu có ý nghĩa hơn (từ kiểu float đến kiểu double). Việc thúc đẩy xảy ra khi bạn thực hiện tính toán trên các biến số thực. Việc tính toán đó đòi hỏi độ chính xác, nếu hai biến khác kiểu việc tính toán sẽ dựa trên biến có ý nghĩa hơn. Cho ví dụ, suy nghĩ về các kiểu khai báo sau:

float f_short;
double f_long;
long double f_longer
f_short = f_short * f_long

Trong ví dụ trên, biến f_short được thúc đẩy đến kiểu double và nhân với f_long; sau đó kết quả được làm tròn đến kiểu float trước khi gán cho f_short.

Trong ví dụ dưới đây (sử dụng khai báo của ví dụ trước), việc tính toán được hoàn thành trên các biến 32-bit; kết quả sẽ được đẩy đến kiểu double.

f_longer  = f_short * f_short




Không có nhận xét nào:

Đăng nhận xét