Tại sao có nhiều loại số (bit, int, float, double, long)?


9

Tôi đã học PHP, Java và C. Bây giờ tôi tò mò về lý do tại sao có rất nhiều loại dữ liệu số như bit, int, float, double và long. Tại sao không chỉ tạo một loại cho số?

Có bất kỳ lợi ích cho điều này? Có lẽ nếu chúng ta sử dụng số nguyên để giữ số lượng nhỏ như vậy, chúng ta có thể tiết kiệm bộ nhớ?


6
Ngoài câu trả lời của HorusKol: các loại 'số nguyên' và 'số nguyên' khác nhau vốn có. Phao có thể chứa số lượng rất lớn, nhưng khi kích thước của số tăng lên, độ chính xác giảm xuống. Sự thiếu chính xác này là do cách lưu trữ phao. Ngược lại, phạm vi giá trị bạn có thể lưu trữ trong một số nguyên khá hạn chế, nhưng giá trị luôn chính xác, do đó bạn có thể so sánh các giá trị dễ dàng hơn nhiều. Ngoài ra, có hai loại hành vi khác nhau với phép chia - số nguyên 'cắt ngắn' thành toàn bộ số gần nhất, số float không. Mỗi hành vi này đều hữu ích cho các tình huống khác nhau.
kampu

Javascript chỉ có một loại số trên bề mặt.
Esailija

@kampu: Trên thực tế, trong nhiều ngôn ngữ, số nguyên có thể lưu trữ bất kỳ số nào miễn là bộ nhớ (ảo) đủ lớn để thể hiện nó.
Jörg W Mittag

1
@ JörgWMittag: Tuy nhiên, người hỏi đó rõ ràng đang nói về các ngôn ngữ tĩnh, chứ không phải các ngôn ngữ động như Python chẳng hạn. Bản thân CPython thực hiện số nguyên 'phạm vi không giới hạn' dưới dạng một mảng gồm 32 bit int, với bit cuối cùng trong mỗi int được sử dụng để cho biết liệu có nhiều bit hơn để đi hay không. Ngoài ra, các số nguyên có thể lưu trữ bất kỳ toàn bộ số duy nhất. Điều đó có nghĩa là một float với lưu trữ vô hạn có thể lưu trữ các giá trị đến độ chính xác (vô cực aleph one), trong khi các số nguyên chỉ có thể lưu trữ các giá trị cho độ chính xác ( vô cực aleph zero ).
kampu

@kampu: Vì tất cả các số được biểu thị bằng chuỗi bit, ngay cả với lưu trữ vô hạn, sẽ luôn có ánh xạ một đến một giữa số nguyên và số nguyên. Vì vậy, tôi không nghĩ rằng aleph người ta đặt câu hỏi.
ĐẾN TỪ

Câu trả lời:


17

Có hai lý do tại sao bạn nên quan tâm đến các loại dữ liệu số khác nhau.

1. Tiết kiệm bộ nhớ

for(long k=0;k<=10;k++)
{
    //stuff
}

Tại sao sử dụng lâu khi nó có thể dễ dàng là một số nguyên, hoặc thậm chí là một byte? Bạn thực sự sẽ tiết kiệm một vài byte bộ nhớ bằng cách làm như vậy.

2. Số dấu phẩy động và số nguyên được lưu trữ khác nhau trong máy tính

Giả sử chúng ta có số 22 được lưu trong một số nguyên. Máy tính lưu số này vào bộ nhớ dưới dạng nhị phân:

0000 0000 0000 0000 0000 0000 0001 0110

Nếu bạn không quen thuộc với hệ thống số nhị phân, điều này có thể được biểu thị bằng ký hiệu khoa học là: 2 ^ 0 * 0 + 2 ^ 1 * 1 + 2 ^ 2 * 1 + 2 ^ 3 * 0 + 2 ^ 4 * 1 + 2 ^ 5 * 0 + ... + 2 ^ 30 * 0. Bit cuối cùng có thể hoặc không thể được sử dụng để cho biết số đó có phải là số âm hay không (tùy thuộc vào kiểu dữ liệu được ký hay không dấu).

Về cơ bản, nó chỉ là tổng của 2 ^ (bit place) * giá trị.

Điều này thay đổi khi bạn đang đề cập đến các giá trị liên quan đến dấu thập phân. Giả sử bạn có số 3,75 trong số thập phân. Điều này được gọi là 11.11 trong nhị phân. Chúng ta có thể biểu thị điều này như một ký hiệu khoa học là 2 ^ 1 * 1 + 2 ^ 0 * 1 + 2 ^ -1 * 1 + 2 ^ -2 * 1 hoặc, được chuẩn hóa, là 1.111 * 2 ^ 2

Tuy nhiên, máy tính không thể lưu trữ điều đó: nó không có phương pháp rõ ràng để biểu thị điểm nhị phân đó (phiên bản hệ thống số nhị phân của dấu thập phân). Máy tính chỉ có thể lưu trữ 1 và 0. Đây là nơi mà kiểu dữ liệu dấu phẩy động xuất hiện.

Giả sử sizeof (float) là 4 byte, thì bạn có tổng cộng 32 bit. Bit đầu tiên được gán "bit dấu". Không có phao không dấu hoặc đôi. 8 bit tiếp theo được sử dụng cho "số mũ" và 23 bit cuối cùng được sử dụng làm "ý nghĩa" (hoặc đôi khi được gọi là lớp phủ). Sử dụng ví dụ 3,75 của chúng tôi, số mũ của chúng tôi sẽ là 2 ^ 1 và ý nghĩa của chúng tôi sẽ là 1.111.

Nếu bit đầu tiên là 1, số âm. Nếu không, tích cực. Số mũ được sửa đổi bởi một thứ gọi là "độ lệch", vì vậy chúng ta không thể lưu trữ "0000 0010" dưới dạng số mũ. Độ lệch cho một số dấu phẩy động chính xác duy nhất là 127 và độ lệch cho độ chính xác kép (đây là nơi mà kiểu dữ liệu kép có tên của nó) là 1023. 23 bit cuối cùng được dành cho ý nghĩa. Ý nghĩa đơn giản là các giá trị cho QUYỀN của điểm nhị phân của chúng tôi.

Số mũ của chúng tôi sẽ là độ lệch (127) + số mũ (1) hoặc được biểu thị dưới dạng nhị phân

1000 0000

Ý nghĩa của chúng tôi sẽ là:

111 0000 0000 0000 0000 0000

Do đó, 3,75 được thể hiện là:

0100 0000 0111 0000 0000 0000 0000 0000

Bây giờ, hãy xem số 8 được biểu thị dưới dạng số dấu phẩy động và dưới dạng số nguyên:

0100 0001 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 1000

Làm thế nào trên thế giới máy tính sẽ thêm 8.0 và 8? Hay thậm chí nhân chúng lên!? Máy tính (cụ thể hơn là máy tính x86) có các phần khác nhau của CPU có thêm số dấu phẩy động và số nguyên.


3
3) mặc dù hiếm khi là một vấn đề: Hoạt động trên các số lớn hơn kích thước từ của máy tính chậm hơn.
Loren Pechtel

6

Quay trở lại trước khi chúng ta có các hệ thống gigabyte (hoặc trên các hệ thống nhúng hiện đại như Arduino), bộ nhớ ở mức cao và do đó các phương pháp tốc ký đã được triển khai để xác định số lượng bộ nhớ cụ thể sẽ chiếm bao nhiêu - BIT đơn giản - ban đầu chỉ chiếm 1 bit của bộ nhớ.

Các kích thước dữ liệu và tên khác nhau giữa các hệ thống. Trên hệ thống 32 bit, INT (hoặc MEDIUMINT) thường là 2 byte, LONGINT sẽ là 4 byte và SMALLINT sẽ là một byte đơn. Các hệ thống 64 bit có thể có LONGINT được đặt ở mức 8 byte.

Ngay cả bây giờ - đặc biệt là trong các ứng dụng cơ sở dữ liệu hoặc các chương trình có nhiều phiên bản đang chạy trên máy chủ (như tập lệnh phía máy chủ trên trang web) - bạn nên cẩn thận về những gì bạn chọn. Chọn một số nguyên rộng 2, 4 hoặc 8 byte để lưu trữ các giá trị trong khoảng từ 0 đến 100 (có thể vừa với một byte) là vô cùng lãng phí nếu bạn có một bảng cơ sở dữ liệu với hàng triệu bản ghi.

Thêm thông tin: https://en.wikipedia.org/wiki/Integer_(computer_science)


câu trả lời hay +1.
Vinay

7
Không chỉ "trở lại trước", mà còn "bây giờ khi một hệ thống nhỏ". Trên một thiết bị, kích thước của Arduino người ta phải tiết kiệm.
9000

1
Hệ thống nào chỉ sử dụng 1 bit để lưu trữ một chút? bit thường không có địa chỉ trực tiếp
jk.

1
điều đó đúng trong rất nhiều kiến ​​trúc - nhưng các bit có thể truy cập trực tiếp trong các hệ thống thực sự cũ và thậm chí một số hệ thống nhúng gần đây (một số bộ điều khiển tôi đã lập trình chỉ 10 năm trước hoạt động với các bit - chúng chỉ có khoảng 64 vị trí có thể định vị theo chiều rộng cụ thể). Ngày nay, tôi đoán các trình biên dịch xử lý nó và đưa chúng vào các mảng byte.
HorusKol

Tôi nghĩ yếu tố quan trọng nhất là khả năng và hiệu suất của CPU chứ không phải là vấn đề về bộ nhớ
James

4

Ngoài những điểm tuyệt vời của cpmjr123 về sự khan hiếm bộ nhớ và độ chính xác và sự đánh đổi phạm vi, những kẻ này cũng có khả năng đánh đổi CPU.

Hầu hết các máy móc hiện đại đều có phần cứng đặc biệt để thực hiện các hoạt động điểm nổi gọi là FPU. Ngoài ra, còn có các hệ thống không có FPU (hiện tại đây là những thiết bị nhúng nhỏ), do đó, tùy thuộc vào phần cứng mục tiêu của bạn, bạn hoàn toàn không phải sử dụng các loại dấu phẩy động hoặc sử dụng thư viện dấu phẩy động phần mềm. Ngay cả khi máy của bạn có một FPU, về mặt lịch sử có những khác biệt về chức năng mà nó có thể cung cấp. Bất kỳ chức năng nào không được thực hiện trong phần cứng sẽ phải được thực hiện trong phần mềm (hoặc tránh)

Thực hiện tính toán dấu phẩy động trong phần mềm được thực hiện bằng cách thực hiện nhiều thao tác đơn giản hơn mà phần cứng hỗ trợ. Do đó, bạn cũng có được một sự đánh đổi tốc độ tiềm năng.


4

Có lẽ điều quan trọng nhất là thực sự có ba loại số cơ bản khác nhau.

số nguyên, số thập phân cố định và dấu phẩy động.

Họ đều cư xử khác nhau.

Một thao tác đơn giản như 7/2 có thể đưa ra câu trả lời là 3, 3.50 và 3.499 tùy thuộc vào loại dữ liệu được sử dụng.

"Số thập phân cố định" là loại Lọ Lem, nó chỉ được hỗ trợ nguyên bản trong một số ngôn ngữ như COBOL và VisualBasic. Nó ít được các nhà khoa học máy tính quan tâm nhưng rất quan trọng đối với bất kỳ ai gửi một bộ tài khoản hoặc tính thuế bán hàng trên hóa đơn.


Tôi tách chúng ra một cách khác nhau: các số rời rạc, số gần đúng và gói các vòng đại số. Ví dụ điển hình trong C sẽ là int, floatunsigned int, tương ứng. Các loại điểm cố định là một thể loại con của các loại rời rạc, nhưng các vòng đại số khác về cơ bản với các số [phải nhầm lẫn về các loại không dấu trong C xuất phát từ thực tế là chúng chủ yếu hoạt động như các vòng thay vì số, nhưng không hoàn toàn nhất quán] .
supercat

3

Có bất kỳ lợi ích họ làm cho nó?

Tất nhiên. Có lợi ích. Trong thế giới của bộ nhớ máy tính là một trong những điều quan trọng nhất để xem xét. Việc sử dụng bộ nhớ 2kb là gì khi dữ liệu có thể vừa với dưới 1kb? . Tối ưu hóa nên có. Nếu bạn sử dụng nhiều bộ nhớ hơn, nó rõ ràng sẽ giết chết tốc độ máy tính của bạn tại một điểm. Bạn có thực sự muốn có nó? Không có quyền...?

int - 2 bytes (16 bits)

long - 4 bytes (32 bits)

long long - 8 bytes (64 bits)

float - 4 bytes

Không chỉ bộ nhớ mà còn có tổ chức các loại số. cho một dấu chấm động. Độ chính xác rất quan trọng và rõ ràng chúng ta nên có một loại có thể cho chúng ta độ chính xác cao hơn.

Nếu chúng ta xem xét ngày xưa, chúng ta có một bộ nhớ rất ít như bạn có thể biết. Để lưu nó và sử dụng nó một cách khôn ngoan, chúng tôi đã có những khác biệt này. Và nhiều hơn nữa nếu bạn cứ tiếp tục và thử một chút tìm kiếm với google .. Hy vọng điều này sẽ giúp.


3

số nguyên và số thực (float, double) là các loại khác nhau về mặt khái niệm với các tập hợp hoạt động và thuộc tính nội tại khác nhau.

Số nguyên là vô số nhưng phao thì không, v.v.

Trong thực tế số Float / double là một cấu trúc kết hợp hai trường số nguyên: mantissa và số mũ. Số phức (mà bạn loại trừ khỏi xem xét) thậm chí còn nhiều hơn, tốt, phức tạp.

Bất kỳ ngôn ngữ thực tế nào cũng phải có ít nhất số nguyên và số float là các loại riêng biệt - các hoạt động quá khác nhau trên chúng.


Tôi không quen thuộc với "số phức" mà bạn đã đề cập. Bạn có thể giải thích thêm?
cpmjr123


Tôi nhận thức được các số phức dưới dạng a + bi. Tôi đã yêu cầu thêm thông tin về cách máy tính lưu trữ các số phức. Theo hiểu biết của tôi, không có loại dữ liệu nguyên thủy nào hỗ trợ điều này.
cpmjr123

Số phức thường được lưu trữ dưới dạng hai giá trị dấu phẩy động, cụ thể là a(phần thực) và b(phần ảo). CPU thường không thực hiện hỗ trợ riêng cho các hoạt động trên các số phức, mặc dù CPU có thể thực hiện các hướng dẫn thêm bội được tăng tốc cho các hoạt động trên các cặp giá trị, chẳng hạn như (a b + c d) và (a b - c d).
rwong

1
Ngoài ra, nhiều ngôn ngữ có một số loại có hành vi được xác định chủ yếu là vòng đại số bao bọc (ví dụ: nếu một biến loại uint16_tgiữ 65535, tăng nó sẽ làm cho nó giữ 0). Lý tưởng nhất là các ngôn ngữ sẽ có các loại tách biệt rõ ràng để biểu diễn các vòng và số đại số (cho phép các số bị tràn bị mắc kẹt, trong khi cho phép mã dễ dàng thực hiện các thao tác trên những thứ được dự kiến ​​sẽ bọc).
supercat

-1

Ngoài ra, thực tế là các loại dấu phẩy động hoạt động hoàn toàn khác với các kiểu số nguyên, tôi muốn đưa ra một ví dụ cực đoan hơn tại sao kích thước trên mỗi số thực sự quan trọng.

Hãy tưởng tượng bạn muốn sắp xếp một mảng (dài). Ví dụ trong C:

int numbers[100000000];

Vì vậy, ở đây chúng tôi có 100 triệu số.

Nếu mỗi số chỉ dài một byte (vì vậy sử dụng unsigned charthay vì int), thì điều này cần 100 triệu byte không gian.

Nếu bạn sử dụng double, thì đây thường là 8 byte mỗi số, vì vậy 800 triệu byte không gian.

Vì vậy, mỗi khi bạn hoạt động với rất nhiều đối tượng (số trong ví dụ này), kích thước cho mỗi đối tượng (kích thước trên mỗi số trong ví dụ này) thực sự có vấn đề.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.