2009-11-07 31 views
9

Sau khi tham gia nhiều hơn vào đào tạo kỹ sư mới cũng như đọc Jon Skeet's DevDays presentation Tôi đã bắt đầu nhận ra nhiều kỹ sư không rõ ràng khi nào nên sử dụng kiểu dữ liệu số nào khi. Tôi đánh giá cao vai trò của một bằng khoa học máy tính chính thức trong việc giúp đỡ điều này, nhưng tôi thấy rất nhiều kỹ sư mới cho thấy sự không chắc chắn vì họ chưa bao giờ làm việc với các tập dữ liệu lớn hoặc phần mềm tài chính hoặc các vấn đề về lập trình hoặc thống kê hoặc các vấn đề về kho dữ liệu phức tạp .Sử dụng kiểu dữ liệu số phải

Trải nghiệm của tôi là mọi người thực sự băn khoăn khi chúng được giải thích trong ngữ cảnh. Tôi đang tìm kiếm các ví dụ tốt về các vấn đề lập trình thực, trong đó dữ liệu nhất định được biểu diễn tốt nhất bằng cách sử dụng kiểu dữ liệu. Cố gắng tránh xa các ví dụ sách giáo khoa nếu có thể. Tôi gắn thẻ này với Java, nhưng cảm thấy tự do để đưa ra các ví dụ trong các ngôn ngữ khác và gắn lại thẻ:

Integer, Long, Double, Float, BigInteger, vv ...

Trả lời

26

Tôi thực sự không nghĩ bạn cần ví dụ hoặc bất kỳ điều gì phức tạp. Điều này rất đơn giản:

  • Đây có phải là số nguyên không?
    • Có thể là> 2^63 không? BigInteger
    • Có thể là> 2^31 không? dài
    • Nếu không int
  • Đây có phải là số thập phân không?
    • Giá trị xấp xỉ có được không?
      • đôi
    • Liệu nó cần phải được chính xác? (Ví dụ: một lượng tiền tệ!)
      • BigDecimal

(Khi tôi nói ">", ý tôi là "lớn về giá trị tuyệt đối", tất nhiên.) Tôi đã không bao giờ sử dụng một byte hoặc char để đại diện cho một số, và tôi đã không bao giờ được sử dụng một khoảng thời gian ngắn. Đó là trong 12 năm lập trình Java. Phao? Meh. Nếu bạn có một mảng lớn và bạn đang gặp vấn đề về bộ nhớ, tôi đoán vậy.

Lưu ý rằng BigDecimal có phần sai tên; các giá trị của bạn làm không phải là phải lớn để cần.

+4

Tôi thực sự thích cách bạn phá vỡ nó. 100% đồng ý với bạn về char, short và Floats với Java. – Scanningcrew

+0

Một gợi ý bổ sung: Nếu đó là số thập phân và cần phải chính xác, nhưng số lượng chữ số thập phân tối đa được biết trước (chẳng hạn như với $ values: 2 dec. Places), thì bạn chỉ có thể sử dụng int/long, và phân chia đầu ra.Đó tránh được các vấn đề với BitDecimal (các toán tử hoạt động, lúng túng). – sleske

4

BigDecimal là tốt nhất khi nói đến việc duy trì tính toán dấu chấm động chính xác và có thể chỉ định độ chính xác mong muốn. Tôi tin rằng nổi (và ở mức độ nào đó tăng gấp đôi) cung cấp lợi ích hiệu suất trên BigDecimal, nhưng với chi phí chính xác và khả năng sử dụng.

+0

+1 để chống lại một số kẻ ngốc đã bỏ phiếu cho câu trả lời này – kar

+0

LOL, cảm ơn bạn! –

1

thường số nếu chúng ta đang nói máy independenat (32/64bit) kích thước kiểu dữ liệu là như dưới đây,

số nguyên: 4 byte dài

: 8 byte

thập phân/float: 4bytes

kép: 8bytes

và kích thước giảm xuống còn một nửa cho các giá trị ký (ví dụ: cho 4bytes, unsigned = 4billions ký = 2billions)

bigInt (phụ thuộc vào việc triển khai ngôn ngữ) đôi khi tối đa 10byte.

để lưu trữ dữ liệu số lượng lớn (chẳng hạn như công cụ tìm kiếm) tôi rất muốn giới thiệu byte và ngắn để tiết kiệm không gian.

byte: 1 byte, (0-256 unsigned, -128 - 128 đã ký)

ngắn: 2 byte (65k unsigned)


giả sử bạn muốn lưu kỷ lục về TUỔI, kể từ khi không ai sống trên 150, vì vậy bạn đã sử dụng kiểu dữ liệu BYTE (đọc ở trên cho kích thước) nhưng nếu bạn sử dụng INTEGER bạn đã lãng phí thêm 3byte và nghiêm túc nói với tôi wth sống hơn 4 tỷ năm.

+1

Ví dụ điển hình về tối ưu hóa sớm ... Trừ khi bạn đang lưu một mảng HUGE hoặc cơ sở dữ liệu của các nhóm tuổi USE INT. Không có nhược điểm nếu kích thước không phải là một vấn đề (và trong hầu hết các trường hợp hiện đại nó không phải) và ngược lại là bạn không rơi cầu nguyện để lỗi ngu ngốc như lỗi Y2K vì tối ưu hóa sớm. –

+0

Tôi đã nói về AGE, không phải ngày sinh lol. hãy tìm hiểu về các chủ đề tôi đã tạo, tôi đã phát triển công cụ tìm kiếm theo quy mô web tùy chỉnh (định dạng chỉ mục được tối ưu hóa cao) trong gần 2 năm và tin tưởng chỉ mục web của tôi là một vấn đề lớn khi tối ưu hóa không gian đĩa. và tôi sử dụng cả INT (32) và LONG (64) cho ngày để tiết kiệm không gian và tránh giới hạn Y2K. – kar

+0

cũng chỉ là FYI sawas, chúng tôi giữ một số dữ liệu của chúng tôi trong 3bytes và 5bytes, tải vào không gian bộ nhớ trong bình thường 4/8bytes cho hiệu quả không gian tối đa thay vì VInt (lucene) cho tốc độ thêm khi tải nó. Vì vậy, có tôi biết những gì im nói về. – kar

4

Một điểm quan trọng bạn có thể muốn nêu rõ là hầu như luôn luôn là lỗi để so sánh các số dấu phẩy động cho sự bình đẳng. Ví dụ: mã sau rất có khả năng không thành công:

double euros = convertToEuros(item.getCostInDollars()); 
if (euros == 10.0) { 
    // this line will most likely never be reached 
} 

Đây là một trong nhiều lý do tại sao bạn muốn sử dụng số rời rạc để biểu thị đơn vị tiền tệ.

Khi bạn hoàn toàn phải so sánh các số dấu phẩy động, bạn chỉ có thể làm như vậy; một cái gì đó trong phạm vi:

double euros = convertToEuros(item.getCostInDollars()); 
if (Math.abs(euros - 10.0) < EPSILON) { 
    // this might work 
} 

Đối với ví dụ thực tế, quy tắc thông thường của tôi nhỏ là một cái gì đó như thế này:

  • kép: suy nghĩ lâu dài và khó khăn trước khi sử dụng nó; đau có đáng không?
  • float: không sử dụng nó
  • byte: thường được sử dụng như byte [] để đại diện cho một số dữ liệu nhị phân thô
  • int: đây là người bạn thân nhất của bạn; sử dụng nó để đại diện cho hầu hết các công cụ
  • dài: sử dụng thẻ này cho dấu thời gian và ID cơ sở dữ liệu
  • BigDecimal and BigInteger: nếu bạn biết về điều này, rất có thể bạn biết mình đang làm gì, vì vậy bạn không cần lời khuyên của tôi

Tôi nhận ra rằng đây không phải là quy tắc khoa học khủng khiếp, nhưng nếu đối tượng mục tiêu của bạn không phải là nhà khoa học máy tính, thì tốt nhất là nên tuân theo những điều cơ bản.

+0

Tôi không phải là một fan hâm mộ lớn của mã ví dụ của bạn, bởi vì bạn không nên sử dụng gấp đôi cho dữ liệu tiền tệ để bắt đầu. Bạn nên sử dụng BigDecimal. Xem ví dụ điều này: http://stackoverflow.com/questions/965831/how-to-parse-a-currency-amount-us-or-eu-to-float-value-in-java/965858#965858 và Mục 48 trong cuốn sách Hiệu quả Java (2nd ed). – Jonik

+2

Jonik - anh ấy cho chúng ta thấy lý do tại sao đôi là xấu. Và anh ấy nói "đây là cách để làm điều đó * nếu bạn hoàn toàn phải * sử dụng dấu phẩy động". Không có lỗi ở đây. –

+0

btw, tôi nghĩ rằng đây là một câu trả lời tuyệt vời, ít nhất là tốt như tôi. ngoại lệ duy nhất là BigDecimal thực sự nên được khuyến khích là cách duy nhất để xử lý các số thập phân một cách chính xác; không chỉ "oh, bạn có thể biết những gì bạn đang làm ..". –

1

VInt trong Lucene là ma quỷ. Lợi ích nhỏ về kích thước là lớn hơn rất nhiều bởi hiệu suất phạt trong việc đọc chúng từng byte một.

Điều tốt để nói đến là không gian so với thời gian giao dịch tắt. Tiết kiệm 200MB là tuyệt vời trong năm 1996, nhưng trong năm 2010, thrashing IO bộ đệm đọc một byte tại một thời điểm là khủng khiếp.

Các vấn đề liên quan