Kiểu số nguyên
Kiểu số nguyên được dùng để lưu trữ số không có dấu thập phân. Nên chọn kiểu này nếu ý nghĩa áp dụng của giá trị không bao gồm phân số. Ví dụ, số thanh trên biểu đồ hoặc số vị trí mở luôn là số nguyên.
MQL5 cho phép chọn các kiểu số nguyên có kích thước 1-8 byte bằng cách sử dụng các từ khóa char
, short
, int
và long
tương ứng. Tất cả chúng đều là kiểu có dấu, tức là chúng có thể chứa cả giá trị dương và giá trị âm. Nếu cần, các kiểu số nguyên có cùng kích thước có thể được khai báo là không dấu (tên của chúng bắt đầu bằng u
cho unsigned
): uchar
, ushort
, uint
và ulong
.
Dựa trên kích thước kiểu và tính có dấu/không dấu, bảng sau đây hiển thị phạm vi giá trị tiềm năng.
Kiểu | Tối thiểu | Tối đa |
---|---|---|
char | -128 | 127 |
uchar | 0 | 255 |
short | -32768 | 32767 |
ushort | 0 | 65535 |
int | -2147483648 | 2147483647 |
uint | 0 | 4294967295 |
long | -9223372036854775808 | 9223372036854775807 |
ulong | 0 | 18446744073709551615 |
Không cần phải ghi nhớ các giá trị giới hạn ở trên cho mỗi số nguyên. Có nhiều hằng số được đặt tên được xác định trước trong MQL5, có thể được sử dụng trong mã thay vì các số 'ma thuật', bao gồm các số nguyên thấp nhất/cao nhất. Công nghệ này được xem xét trong phần xử lý trước. Ở đây, chúng ta chỉ liệt kê các hằng số được đặt tên có liên quan: CHAR_MIN
, CHAR_MAX
, UCHAR_MAX
, SHORT_MIN
, SHORT_MAX
,USHORT_MAX
, INT_MIN
, INT_MAX
, UINT_MAX
, LONG_MIN
, LONG_MAX
và ULONG_MAX
.
Chúng ta hãy giải thích cách thu được các giá trị này. Điều này đòi hỏi phải quay lại với bit và byte.
Số lượng tất cả các kết hợp có thể có của các trạng thái khác nhau của 8 bit, được bật và tắt, trong một byte, là 256
. Điều này tạo ra phạm vi giá trị 0-255
có thể được lưu trữ trong một byte. Tuy nhiên, việc diễn giải chúng phụ thuộc vào loại mà byte này được phân bổ. Trình biên dịch đảm bảo các diễn giải khác nhau, theo các tuyên bố của lập trình viên.
Bit bậc thấp (ngoài cùng bên phải) trong một byte có nghĩa là 1, bit thứ hai là 2, bit thứ ba là 4, v.v. cho đến bit bậc cao có nghĩa là 128. Có thể thấy rõ ràng rằng các số này bằng hai lũy thừa bằng số bit (đánh số bắt đầu từ 0). Đây là hiệu ứng của việc sử dụng hệ nhị phân.
Bits | High order | - | - | - | - | - | - | Low order |
---|---|---|---|---|---|---|---|---|
Number | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Value | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
Khi tất cả các bit được đặt, điều này tạo ra tổng của tất cả các lũy thừa của hai, tức là 255
là giá trị cao nhất cho một byte. Nếu tất cả các bit được đặt lại, chúng ta sẽ nhận được số không. Nếu một bit bậc thấp được bật, số đó là số lẻ.
Trong mã hóa số có dấu, bit bậc cao được dùng để đánh dấu các giá trị âm. Do đó, đối với một số nguyên một byte trong phạm vi dương, 127
trở thành giá trị cao nhất. Đối với các giá trị âm, có 128
tổ hợp có thể, tức là giá trị thấp nhất là -128
. Khi tất cả các bit trong một byte được đặt, nó được diễn giải là -1
. Nếu bit bậc thấp được đặt lại trong một số như vậy, chúng ta sẽ nhận được -2
, v.v. Nếu chỉ có bit bậc cao (dấu) được đặt và tất cả các bit khác được đặt lại, chúng ta nhận được -128
.
Mã hóa này có vẻ phi lý được gọi là "additional". Nó cho phép bạn thống nhất các phép tính của số có dấu và không dấu ở cấp độ phần cứng. Hơn nữa, nó cho phép bạn không mất một giá trị nào, điều này sẽ xảy ra nếu các vùng dương và âm được mã hóa giống hệt nhau: Khi đó, chúng ta sẽ có hai giá trị cho số không, tức là một số 0
dương và một số 0
âm. Hơn nữa, điều này sẽ gây ra sự mơ hồ.
Các số có nhiều byte hơn, tức là 2, 4 hoặc 8, có số bit liên tiếp tương tự nhau và tiến trình của các giá trị tương ứng của chúng. Trong mọi trường hợp, tiêu chí cho số âm là bit bậc cao được đặt của byte bậc cao.
Do đó, chúng ta có thể sử dụng một byte để lưu trữ một số nguyên không dấu ( uchar
, tức là ký tự không dấu được viết tắt) trong phạm vi từ 0-255
. Chúng ta cũng có thể viết một số nguyên có dấu vào byte (vì mục đích này, chúng ta sẽ mô tả kiểu của nó là char
). Trong trường hợp này, trình biên dịch sẽ chia đều số lượng kết hợp có sẵn của 256 giữa các giá trị dương và âm, sau khi hiển thị nó vào vùng từ -128
đến 127
(giá trị thứ 256
là số không). Rõ ràng là các giá trị 0-127
sẽ được mã hóa đều ở cấp độ bit cho các byte có dấu và không dấu. Tuy nhiên, các giá trị tuyệt đối lớn, bắt đầu từ 128, sẽ chuyển thành giá trị âm (theo sơ đồ được mô tả trong phần chèn ở trên). "Chuyển đổi" này chỉ diễn ra tại thời điểm đọc hoặc thực hiện bất kỳ thao tác nào với giá trị được lưu trữ, với biểu diễn dữ liệu nội bộ giống hệt nhau (trạng thái của các bit).
Chúng ta sẽ xem xét vấn đề này chi tiết hơn trong phần nói về ép kiểu.
Tương tự như với số nguyên một byte, có thể dễ dàng tính toán rằng số tổ hợp bit là 65536
cho 2 byte. Do đó, các phạm vi được hình thành cho số nguyên hai byte có dấu và không dấu, short
và ushort
. Các kiểu khác cho phép lưu trữ các giá trị thậm chí còn lớn hơn do tăng kích thước byte của chúng.
Xin lưu ý rằng việc sử dụng kiểu không dấu có cùng kích thước cho phép nhân đôi giá trị dương cao nhất. Điều này có thể cần thiết để lưu trữ số lượng có khả năng rất lớn, mà không có giá trị âm nào có thể xuất hiện. Ví dụ, số thứ tự trong MetaTrader 5 là giá trị của kiểu ulong
.
Chúng ta đã gặp các mẫu mô tả số nguyên trong Phần 1. Đặc biệt, tham số đầu vào GreetingHour
thuộc kiểu uint
đã được định nghĩa ở đó:
input uint GreetingHour = 0;
Ngoại trừ từ khóa bổ sung, input
, giúp biến hiển thị trong danh sách tham số của chương trình MQL, các thành phần khác, tức là kiểu, tên và khởi tạo tùy chọn sau dấu =
, là nội tại đối với tất cả các biến.
Cú pháp mô tả biến sẽ được xem xét chi tiết trong phần Biến. Cho đến nay, vui lòng lưu ý phương pháp ghi lại các hằng số kiểu số nguyên. Khi mô tả một biến, hằng số có thể được chỉ định là giá trị mặc định (trong ví dụ trên, là 0). Hơn nữa, hằng số có thể được sử dụng trong các biểu thức, ví dụ, trong một sự kiện công thức.
Cần lưu ý rằng các hằng số của bất kỳ loại nào, được chèn vào mã nguồn, đều được đặt tên là literal (theo văn bản: "word-for-word"). Tên của chúng bắt nguồn từ thực tế là chúng được đưa vào chương trình "nguyên trạng" và được sử dụng ngay tại điểm mô tả. Các literal, không giống như nhiều thành phần khác của ngôn ngữ, đặc biệt là các biến, không có tên và không thể được tham chiếu từ các điểm khác của chương trình.
Đối với số âm, cần phải thêm dấu trừ -
trước số đó; tuy nhiên, có thể bỏ dấu cộng '+' đối với số dương, nghĩa là dạng +100
và chỉ 100
là giống hệt nhau.
Cần lưu ý rằng các giá trị số thường được ghi lại trong mã nguồn theo ký hiệu thập phân thông thường của chúng ta. Tuy nhiên, MQL5 cho phép sử dụng ký hiệu còn lại, tức là thập lục phân. Nó thuận tiện cho việc xử lý thông tin cấp bit (xem Toán tử bitwise).
Các số từ 0 đến 9 được phép trong tất cả các số theo thứ tự chữ số trong hằng số thập phân, trong khi đối với các số thập lục phân, cùng với các chữ số, các ký hiệu Latin từ A đến F hoặc từ a đến f (tức là không phân biệt chữ hoa chữ thường) được sử dụng bổ sung. "Chữ số thập lục phân" A tương ứng với số 10 của ký hiệu thập phân, B — 11, C — 12, v.v., lên đến F bằng 15.
Một đặc điểm riêng biệt của một hằng số thập lục phân là nó bắt đầu bằng tiền tố
0x
hoặc0X
, theo sau là thứ tự chữ số có nghĩa của số. Ví dụ, số 1 được ghi là0x1
trong hệ thập lục phân, trong khi 16 là0x10
(cần thêm một chữ số có thứ tự cao hơn vì 16 lớn hơn 15, tức là 0xF). Số thập phân 255 chuyển thành0xFF
.
Chúng ta hãy đưa ra thêm một số ví dụ minh họa các tình huống khác nhau khi sử dụng kiểu số nguyên để mô tả các biến (được đính kèm trong tập lệnh MQL5/Scripts/MQL5Book/p2/TypeInt.mq5
):
void OnStart () {
int x = -10; // ok, số nguyên có dấu x = -10
uint y = -1; // ok, nhưng số nguyên không dấu y = 4294967295
int z = 1.23; // cảnh báo: cắt bớt giá trị hằng số, z = 1
short h = 0x1000; // ok, h = 4096 ở dạng thập phân
long p = 10000000000; // ok
int w = 10000000000; // cảnh báo, cắt bớt..., w = 1410065408
}
2
3
4
5
6
7
8
- Biến x được khởi tạo đúng bằng giá trị âm được phép là
-10
. - Biến y không dấu. Do đó, một nỗ lực ghi lại giá trị âm trong đó dẫn đến một hiệu ứng thú vị. Số -1 có biểu diễn bằng bit, được chương trình diễn giải theo kiểu không dấu,
uint
. Do đó, số4294967295
thu được (thực tế bằngUINT_MAX
). - Biến z được gán số dấu phẩy động 1.23 (chúng sẽ được xem xét trong phần tiếp theo) và trình biên dịch cảnh báo về việc cắt bớt phần phân số. Kết quả là, số nguyên 1 được đưa vào biến.
- Biến h được khởi tạo thành công bằng hằng số ở dạng thập lục phân (0x1000 = 4096).
- Giá trị lớn 10000000000 được ghi lại trong các biến p và w , trong đó biến p là kiểu số nguyên dài ( long ) và được xử lý thành công, trong khi biến w là kiểu bình thường ( int ) và do đó, yêu cầu cảnh báo trình biên dịch. Vì hằng số vượt quá giá trị tối đa cho
int
, trình biên dịch cắt bớt các chữ số bậc cao (bit) dư thừa và trên thực tế, 1410065408 được đưa vào w.
Hành vi này là một trong những diễn biến tiêu cực tiềm ẩn của chuyển đổi kiểu mà lập trình viên có thể ngụ ý hoặc không. Trong trường hợp sau, nó chứa đầy lỗi tiềm ẩn. Rõ ràng, trong ví dụ cụ thể này, các giá trị sai đã được cố ý chọn để chứng minh cảnh báo. Không phải lúc nào cũng rõ ràng trong một chương trình thực tế, chương trình đang cố gắng lưu các giá trị nào trong biến số nguyên. Do đó, bạn nên xem xét các cảnh báo của trình biên dịch rất cẩn thận và cố gắng loại bỏ chúng, sau khi đã thay đổi kiểu hoặc chỉ định rõ ràng kiểu ép kiểu bắt buộc. Điều này sẽ được xem xét trong phần xử lý Typecasting.
Đối với các kiểu số nguyên, các phép toán số học, bitwise và các kiểu phép toán khác được xác định (xem chương Biểu thức).