Cách hiệu quả nhất để lưu trữ một phạm vi số là gì?


29

Câu hỏi này là về bao nhiêu bit được yêu cầu để lưu trữ một phạm vi. Hoặc đặt một cách khác, đối với một số bit nhất định, phạm vi tối đa có thể được lưu trữ là gì và bằng cách nào?

Hãy tưởng tượng chúng ta muốn lưu trữ một phạm vi phụ trong phạm vi 0-255.

Vì vậy, ví dụ, 45-74.

Chúng ta có thể lưu trữ ví dụ trên dưới dạng hai byte không dấu, nhưng nó cho tôi thấy rằng phải có một số thông tin dư thừa ở đó. Chúng ta biết rằng giá trị thứ hai lớn hơn giá trị thứ nhất, vì vậy trong trường hợp giá trị thứ nhất lớn, cần ít bit hơn cho giá trị thứ hai và trong trường hợp giá trị thứ hai lớn hơn, cần ít bit hơn cho giá trị thứ nhất .

Tôi nghi ngờ rằng bất kỳ kỹ thuật nén nào cũng sẽ mang lại kết quả cận biên, vì vậy có thể là một câu hỏi tốt hơn để hỏi "phạm vi tối đa có thể được lưu trữ trong một byte là gì?". Điều này nên lớn hơn những gì có thể đạt được bằng cách lưu trữ hai số riêng biệt.

Có bất kỳ thuật toán tiêu chuẩn để làm loại điều này?


Bạn cũng phải lưu trữ bắt đầu của phạm vi?
Ewan

@Ewan Tôi không thực sự làm theo. Trong ví dụ trên, 45 là bắt đầu (tối thiểu) và 74 là kết thúc (tối đa) và cả hai phải được lưu trữ.
rghome

2
vậy là câu hỏi có bao nhiêu không gian mà một loại có thể lưu trữ bất kỳ phạm vi nào yêu cầu. hoặc một loại có thể lưu trữ 45-74 cần bao nhiêu dung lượng?
Ewan

1
Trong khi suy nghĩ về điều này chắc chắn là tốt, tôi chắc chắn hy vọng bạn không làm điều này trong các ứng dụng thực tế. Lý do là số lượng phức tạp của các ứng dụng thực tế rất lớn đến nỗi chúng tôi phải chấp nhận mã được tối ưu hóa dưới 100% .... Đó là lý do tại sao trình biên dịch tồn tại.
NoChance

3
@rghome, tôi đồng ý, ngay cả yêu cầu đơn giản nhất cũng tạo ra hàng trăm dòng mã. Mỗi cái đều dễ bị lỗi. Cá nhân, tôi sẽ trả tiền cho phần cứng hơn là tăng độ phức tạp của phần mềm.
NoChance

Câu trả lời:


58

Chỉ cần đếm số lượng phạm vi có thể. Có 256 phạm vi có giới hạn dưới 0 (0-0, 0-1, ... 0-254, 0-255), 255 phạm vi có giới hạn dưới 1, ... và cuối cùng là 1 phạm vi có giới hạn dưới 255 (255- 255). Vậy tổng số là (256 + 255 + ... + 1) = 257 * 128 = 32.896. Vì giá trị này cao hơn một chút so với 2 15 = 32.768, bạn sẽ vẫn cần ít nhất 16 bit (2 byte) để lưu trữ thông tin này.

Nói chung, đối với các số từ 0 đến n-1, số lượng phạm vi có thể là n * (n + 1) / 2. Giá trị này nhỏ hơn 256 nếu n từ 22 trở xuống: n = 22 cho 22 * ​​23/2 = 253 khả năng. Vì vậy, một byte đủ cho các phạm vi phụ là 0-21 .

Một cách khác để xem xét vấn đề là như sau: lưu trữ một cặp số nguyên trong phạm vi 0 đến n-1 gần giống như lưu trữ một phạm vi con 0- (n-1) cộng với một bit xác định nếu là số đầu tiên thấp hơn hoặc cao hơn cái thứ hai. (Sự khác biệt đến từ trường hợp khi cả hai số nguyên bằng nhau, nhưng cơ hội này sẽ ngày càng nhỏ hơn khi n ngày càng lớn.) Đó là lý do tại sao bạn chỉ có thể tiết kiệm khoảng một bit với kỹ thuật này và có lẽ là lý do chính tại sao nó hiếm khi được sử dụng.


Cảm ơn. Số lượng bit cần thiết cho n phạm vi là log (n) / log2. Cung cấp tất cả vào Wolfram Alpha đã cho tôi công thức tương thích Excel sau để tính giá trị tối đa cho phân vùng cho một số bit đã cho: = INT ((SQRT (POWER (2, N + 3) + 1) - 1) / 2 )
rghome

9
TLDR là bạn kiếm được khoảng một nửa, vì vậy nói chung nó không thực sự đáng nén.
rghome

Vâng, nó có xu hướng một chút cho N lớn nhưng nó không thực sự đáng phiền phức.
Glorfindel

FYI, N + 3 trong phương trình có vẻ kỳ lạ, nhưng một lũy thừa 2 xuất phát từ phương trình của bạn và hai phần còn lại đến từ phần 4ac của công thức bậc hai.
rghome

1
BTW, số đếm của bạn giảm giá phạm vi trống, trong đó tất cả các kết hợp không được tính đứng. Vì vậy, n * (n + 1) / 2 + 1! Một sự thay đổi rất nhỏ.
Ded repeatator

17

Đối với số lượng bit nhỏ như vậy, việc lưu nhiều bit như Glorfindel đã chỉ ra là không thể . Tuy nhiên, nếu tên miền bạn đang sử dụng có thêm một vài bit, bạn có thể đạt được mức tiết kiệm đáng kể cho trường hợp trung bình bằng cách mã hóa phạm vi với giá trị bắt đầu và delta.

Giả sử miền là số nguyên, vì vậy 32 bit. Với cách tiếp cận ngây thơ, bạn cần 64 bit (bắt đầu, kết thúc) để lưu trữ một phạm vi.

Nếu chúng ta chuyển sang mã hóa (bắt đầu, delta), chúng ta có thể xây dựng phần cuối của phạm vi từ đó. Chúng ta biết rằng trong trường hợp xấu nhất, bắt đầu là 0 và delta có 32 bit.

2 ^ 5 là 32, vì vậy chúng tôi mã hóa độ dài của delta theo năm bit (không có độ dài bằng 0, luôn luôn thêm 1) và mã hóa trở thành (bắt đầu, chiều dài, delta). Trong trường hợp xấu nhất, chi phí này là 32 * 2 + 5 bit, do đó 69 bit. Vì vậy, trong trường hợp xấu nhất, nếu tất cả các phạm vi dài, điều này tồi tệ hơn thì mã hóa ngây thơ.

Trong trường hợp tốt nhất, nó có giá 32 + 5 + 1 = 38 bit.

Điều này có nghĩa nếu bạn có để mã hóa rất nhiều phạm vi, và những dao động mỗi chỉ bao gồm một phần nhỏ của tên miền của bạn, bạn sẽ chỉ sử dụng ít không gian trên trung bình sử dụng mã hóa này. Việc bắt đầu được phân phối như thế nào không quan trọng, vì khởi đầu sẽ luôn mất 32 bit, nhưng vấn đề là độ dài của các phạm vi được phân phối như thế nào. Nếu bạn càng có nhiều độ dài nhỏ, thì nén càng tốt, bạn càng có nhiều phạm vi bao trùm toàn bộ chiều dài của miền, mã hóa này sẽ càng tệ hơn.

Tuy nhiên, nếu bạn có nhiều phạm vi được nhóm xung quanh các điểm bắt đầu tương tự, (ví dụ vì bạn nhận được các giá trị từ một cảm biến), bạn có thể đạt được mức tiết kiệm thậm chí còn lớn hơn. Bạn có thể áp dụng kỹ thuật tương tự cho giá trị bắt đầu và sử dụng độ lệch để bù giá trị bắt đầu.

Hãy nói rằng bạn có 10000 phạm vi. Các phạm vi được nhóm xung quanh một giá trị nhất định. Bạn mã hóa sai lệch với 32 bit.

Sử dụng phương pháp ngây thơ, bạn sẽ cần 32 * 2 * 10 000 = 640 000 bit để lưu trữ tất cả các phạm vi đó.

Mã hóa sai lệch mất 32 bit và mã hóa mỗi phạm vi trong trường hợp tốt nhất sau đó 5 + 1 + 5 + 1 = 12 bit, với tổng số 120 000 + 32 = 120 032 bit. Trong trường hợp xấu nhất, bạn cần 5 + 32 + 5 + 32 bit, do đó 74 bit, với tổng số 740 032 bit.

Điều này có nghĩa, với 10 000 giá trị trên một miền cần 32 bit để mã hóa, chúng tôi nhận được

  • 120 032 bit với mã hóa delta thông minh trong trường hợp tốt nhất
  • 640 000 bit với khởi đầu ngây thơ, mã hóa kết thúc, luôn luôn (không có trường hợp tốt nhất hoặc tồi tệ nhất)
  • 740 032 bit với mã hóa delta thông minh trong trường hợp xấu nhất

Nếu bạn lấy mã hóa ngây thơ làm cơ sở, điều đó có nghĩa là tiết kiệm tới 81,25% hoặc chi phí cao hơn tới 15,625%.

Tùy thuộc vào cách các giá trị của bạn được phân phối, những khoản tiết kiệm đó rất đáng kể. Biết lĩnh vực kinh doanh của bạn! Biết những gì bạn muốn mã hóa.

Là một phần mở rộng, bạn cũng có thể thay đổi sự thiên vị. Nếu bạn phân tích dữ liệu và xác định các nhóm giá trị, bạn có thể sắp xếp dữ liệu thành các nhóm và mã hóa từng nhóm đó một cách riêng biệt, với độ lệch riêng. Điều này có nghĩa là bạn có thể áp dụng kỹ thuật này không chỉ cho các phạm vi được nhóm xung quanh một giá trị bắt đầu mà còn cho các phạm vi được nhóm xung quanh nhiều giá trị.

Nếu điểm bắt đầu của bạn được phân phối đều, mã hóa này không thực sự hoạt động tốt.

Mã hóa này rõ ràng là cực kỳ xấu để lập chỉ mục. Bạn không thể đơn giản đọc giá trị x-th. Nó có thể khá nhiều chỉ được đọc tuần tự. Điều này phù hợp trong một số trường hợp, ví dụ: phát trực tuyến qua mạng hoặc lưu trữ hàng loạt (ví dụ: trên băng hoặc ổ cứng).

Đánh giá dữ liệu, nhóm nó và chọn độ lệch chính xác có thể là công việc đáng kể và có thể yêu cầu một số tinh chỉnh để có kết quả tối ưu.


8

Loại vấn đề này là chủ đề của bài báo chuyên đề của Claude Shannon, Một lý thuyết toán học về truyền thông , đã giới thiệu từ "bit bit bit" và ít nhiều phát minh ra dữ liệu nén.

Ý tưởng chung là số bit được sử dụng để mã hóa một phạm vi tỷ lệ nghịch với xác suất của phạm vi đó xảy ra. Ví dụ: giả sử phạm vi 45-74 xuất hiện khoảng 1/4 thời gian. Bạn có thể nói rằng chuỗi 00 tương ứng với 45-74. Để mã hóa phạm vi 45-74, bạn xuất ra 00 00 và dừng ở đó.

Chúng ta cũng giả sử rằng các phạm vi 99-100 và 140-155 mỗi lần xuất hiện khoảng 1/8 thời gian. Bạn có thể mã hóa từng cái với chuỗi 3 bit. Bất kỳ 3 bit nào cũng sẽ hoạt động miễn là chúng không bắt đầu với khăn 00 00, vốn đã được dành riêng cho phạm vi 45-74.

00: 45-74
010: 99-100
101: 140-155

Bạn có thể tiếp tục theo cách này cho đến khi mọi phạm vi có thể có mã hóa. Phạm vi có thể xảy ra ít nhất có thể cần hơn 100 bit. Nhưng điều đó không sao vì nó hiếm khi xuất hiện.

các thuật toán để tìm mã hóa tối ưu. Tôi sẽ không cố gắng giải thích chúng ở đây, nhưng bạn có thể tìm thấy nhiều hơn bằng cách truy cập vào liên kết ở trên hoặc tìm kiếm Lý thuyết thông tin, thuật ngữ, thuật toán mã hóa, thuật toán mã hóa, thuật toán mã hóa, thuật toán mã hóa dữ liệu.

Như những người khác đã chỉ ra, có lẽ tốt hơn để lưu trữ số bắt đầu và sự khác biệt giữa số bắt đầu và số kết thúc. Bạn nên sử dụng một mã hóa cho sự khởi đầu và một mã hóa khác cho sự khác biệt, vì chúng có các phân phối xác suất khác nhau (và tôi đoán rằng mã sau là dư thừa hơn). Như polygnome đề xuất, thuật toán tốt nhất phụ thuộc vào miền của bạn.


1
Vâng, lĩnh vực kinh doanh là thực sự quan trọng. Chúng tôi thực sự đã cân nhắc sử dụng mã hóa Huffmann cho các thành kiến ​​cho ngày bắt đầu, nhưng cuối cùng đã quyết định chống lại nó sau khi chạy một số phân tích thống kê về dữ liệu trong thế giới thực. Đơn giản việc sử dụng cùng một mã hóa cho thiên vị và delta là quan trọng hơn sau đó thêm Huffmann lên trên cùng, ngoài ra bạn cũng cần gửi toàn bộ cây Huffmann. Đó là một ý tưởng tốt để giữ Huffmann mã hóa trong tâm trí mặc dù.
Polygnome

1

Để mở rộng câu trả lời từ @Glorfindel:

Khi n →, (n - 1) → n. Do đó, Ω (phạm vi) → n² / 2 và log (Ω (phạm vi)) → (2n - 1). Vì mã hóa ngây thơ mất 2n bit, nên nén tối đa tiệm cận chỉ tiết kiệm được 1 bit.


1

Có một câu trả lời tương tự, nhưng để đạt được nén tối ưu, bạn cần:

  1. Một phương pháp mã hóa entropy tối ưu (đọc mã hóa Số học và về cơ bản tương đương (cùng tỷ lệ nén, nhanh hơn một chút nhưng cũng khó nắm bắt hơn) ANS )
  2. Càng nhiều thông tin càng tốt về việc phân phối dữ liệu. Điều quan trọng, điều này không chỉ liên quan đến việc "đoán" tần suất một số có thể xuất hiện, nhưng bạn thường có thể loại trừ một số khả năng chắc chắn. Ví dụ: bạn có thể loại trừ các khoảng có kích thước âm và có thể là 0 kích thước, tùy thuộc vào cách bạn xác định khoảng thời gian hợp lệ. Nếu bạn có nhiều khoảng thời gian để mã hóa cùng một lúc, bạn có thể sắp xếp chúng, ví dụ theo thứ tự giảm chiều rộng hoặc tăng giá trị bắt đầu / kết thúc và loại trừ rất nhiều giá trị (ví dụ: nếu bạn đảm bảo đơn hàng bằng cách giảm độ rộng, khoảng trước đó có chiều rộng là 100 và giá trị bắt đầu cho lần tiếp theo là 47, bạn chỉ cần xem xét các khả năng lên tới 147 cho các giá trị cuối).

Điều quan trọng, số 2 có nghĩa là bạn muốn mã hóa mọi thứ theo cách mà các giá trị thông tin nhất (trên mỗi bit được mã hóa) xuất hiện trước. Ví dụ, trong khi tôi đề nghị mã hóa một danh sách được sắp xếp "nguyên trạng", thông thường sẽ thông minh hơn để mã hóa nó dưới dạng "cây nhị phân" - tức là nếu chúng được sắp xếp theo chiều rộng và bạn có lencác phần tử, hãy bắt đầu bằng phần tử mã hóa len/2. Nói rằng nó có chiều rộng w. Bây giờ bạn đã biết tất cả các phần tử trước khi nó có chiều rộng ở đâu đó trong [0, w] và tất cả các phần tử sau nó có chiều rộng ở đâu đó trong [w, max val bạn chấp nhận]. Lặp lại đệ quy (chia lại một nửa danh sách một nửa, v.v.) cho đến khi bạn bao phủ lencác phần tử (trừ khi nó được cố định, bạn sẽ muốn mã hóalentrước tiên, do đó bạn không cần bận tâm đến việc kết thúc mã thông báo). Nếu "max val bạn chấp nhận" thực sự mở, có thể là thông minh trước tiên mã hóa giá trị cao nhất thực sự xuất hiện trong dữ liệu của bạn, tức là phần tử cuối cùng, sau đó thực hiện phân vùng nhị phân. Một lần nữa, bất cứ điều gì là thông tin nhất trên mỗi bit đầu tiên.

Ngoài ra, nếu bạn mã hóa độ rộng của khoảng thời gian trước và bạn biết giá trị tối đa có thể bạn đang xử lý, rõ ràng bạn có thể loại trừ tất cả các giá trị bắt đầu sẽ khiến nó tràn ra ... bạn hiểu ý. Chuyển đổi và sắp xếp dữ liệu của bạn theo cách mà bạn có thể suy luận càng nhiều càng tốt về phần còn lại của dữ liệu khi bạn giải mã nó và thuật toán mã hóa entropy tối ưu sẽ đảm bảo bạn không lãng phí bit mã hóa thông tin mà bạn "đã biết" .

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.