Giả sử một thuật toán nén đơn giản biểu thị một lần chạy a
bằng cách lưu trữ , tức là một số tiêu đề cố định, chuỗi và số lần lặp lại . Đây là một mã hóa độ dài chạy . Khi đó độ dài của văn bản nén sẽ gần với bit cho một số hằng số . Tỷ lệ nén tương ứng sẽ là . Đây gần như là hình dạng của đường cong khi nhìn từ xa, nếu bạn bỏ bê những thăng trầm cục bộ. Không có triệu chứng, tỷ lệ nén là vớin a + lg n a( tiêu đề , "a" , n )a
na + lgnmột Θ(lg(n)p/n)p≥1a + lg( n )nΘ ( lg( n )p/ n)p ≥ 1(Tôi đã không giải quyết được nhưng tôi nghi ngờ có những yếu tố khác đang diễn ra làm cho kích thước của siêu tuyến đầu ra theo chiều dài của chuỗi đầu vào).
n a n a + 1 a + 2 algn bit không phải là số bit nguyên, chứ đừng nói đến byte: kích thước của phải ở mức tối thiểu được làm tròn lên đến số byte nguyên. Điều này giải thích tác dụng ngưỡng đầu tiên: cho thuật toán nén đơn giản này, bạn sẽ nhận thấy rằng chiều dài của đầu ra là khi là đủ nhỏ, sau đó , sau đó vv Tỷ lệ nén do đó không phải là một đường cong mượt mà nhưng nhảy từ sang , sau đó , v.v. nhưng có những hiệu ứng khác khi chơi làm cho các bước nhảy khác nhau).nmộtna + 1a + 2 a+1mộtn a+2a + 1na + 2n
Do tỷ lệ nén quá gần với tỷ lệ nghịch của độ dài để quan sát trực quan, nên đây là dữ liệu cho độ dài nhỏ trong triển khai của tôi (điều này có thể phụ thuộc vào phiên bản của thư viện bzip2, vì có nhiều cách để nén một số đầu vào ). Cột đầu tiên cho biết số lượng a
, cột thứ hai là chiều dài của đầu ra được nén.
1–3 37
4–99 39
100–115 37
116–258 39
259–354 45
355 43
356 40
357–370 41
371–498 43
499–513 41
514–609 45
610 43
611 41
613–625 42
626–753 44
754–764 42
765 40
766–767 41
768 42
769–864 45
…
Bzip2 phức tạp hơn nhiều so với mã hóa độ dài chạy đơn giản. Nó hoạt động theo một loạt các bước và bước đầu tiên là bước mã hóa có độ dài chạy , nhưng với giới hạn kích thước cố định. Bước đầu tiên hoạt động như sau: nếu một byte được lặp lại ít nhất 4 lần, sau đó thay thế các byte sau lần thứ 4 bằng một byte cho biết số lần lặp lại của các byte bị xóa. Ví dụ, aaaaaaa
được chuyển đổi thành aaaa\d{3}
( \d{003}
ký tự có giá trị byte 3); aaaa
được chuyển đổi aaaa\d{0}
, và như vậy. Vì chỉ có 256 giá trị byte riêng biệt, nên chỉ các chuỗi trong đó byte được lặp lại tới 259 lần có thể được mã hóa theo cách này; nếu có nhiều hơn, một chuỗi mới bắt đầu. Hơn nữa, việc thực hiện tham chiếu dừng lại ở số đếm lặp lại là 252, mã hóa chuỗi 256 byte.
Bước này giải thích ngưỡng đầu tiên và ngưỡng ở mức 258: nén thành 37 byte cho và tối đa 39 byte cho . Việc giới thiệu số đếm lặp lại dẫn đến thêm 2 byte trong đầu ra của các bước tiếp theo và byte bổ sung đó có thể biểu thị tất cả số đếm lặp lại lên tới 258. Sau 258 byte, có chuỗi RLE thứ hai. Có cái thứ ba ở mức 514 byte, cái thứ tư ở mức 769 byte, v.v. Các chuỗi RLE bổ sung sau chuỗi thứ hai hoàn toàn không tốn nhiều chi phí vì chuỗi đó (giả sử đó là số lần lặp lại, tôi chưa kiểm tra) tự lặp lại và do đó được nén bởi các bước tiếp theo. 1≤n≤34≤n≤258mộtn1 ≤ n ≤ 34 ≤ n ≤ 258aaaa\d{252}
\d{252}
Tại sao các ngưỡng ở mức 258, 516, 769, (không có ở 1024), 1279 chứ không phải là bội số chính xác của 256? Tôi nghi ngờ đó là vì phép biến đổi Burrows-Wheeler theo sau chuyển từ phía trước có thể biến đổi một cái gì đó giống như aaaa\374aa
(đầu ra của bước 1 cho ) bằng cách di chuyển chúng lại với nhau để chúng có thể được mã hóa cùng nhau, nhưng tôi không đã kiểm tra.n = 258a
Việc giảm chiều dài ở rất thú vị. Đối với đầu vào , bước RLE đầu tiên tạo ra - nhưng giá trị byte là 97, vì vậy đây là tiềm năng tốt hơn để nén theo các bước tiếp theo. Tôi nghi ngờ rằng hiệu ứng thu hẹp không chỉ đối với mà còn đối với các giá trị xung quanh là do bước mã hóa delta giúp lưu trữ byte với các giá trị gần đó dễ dàng hơn. Nếu bạn thay đổi thành (65), bạn sẽ nhận thấy rằng đầu ra ngắn hơn xảy ra trong .một 101 n = 101 68 ≤ n ≤ 83n = 100a101aaaa\d{97}
a
aaaaa
n=101a
A
68≤n≤83
Phân tích của tôi về ví dụ này là không đầy đủ. Để hiểu các hiệu ứng khác, bạn sẽ phải nghiên cứu các bước khác của phép chuyển đổi: Tôi chủ yếu dừng lại sau bước 1 trên 9. Tôi hy vọng điều này mang đến cho bạn ý tưởng về lý do tại sao các tỷ lệ nén có một chút biến đổi và không thay đổi đơn điệu. Nếu bạn thực sự muốn tìm hiểu từng chi tiết, tôi khuyên bạn nên thực hiện một triển khai hiện có và quan sát nó với trình gỡ lỗi.
Đối với hầu hết các phần, các biến thể phút như vậy không phải là trọng tâm chính khi thiết kế thuật toán nén: trong nhiều tình huống phổ biến, chẳng hạn như thuật toán nén đa mục đích hoặc phương tiện, sự khác biệt của một vài byte là không liên quan. Nén cố gắng vắt kiệt từng bit ở cấp độ cục bộ và cố gắng xâu chuỗi các biến đổi theo cách để đạt được thường xuyên trong khi hiếm khi mất và sau đó không nhiều. Tuy nhiên, có những tình huống như các giao thức truyền thông có mục đích đặc biệt được thiết kế cho giao tiếp băng thông thấp trong đó mọi bit đều quan trọng. Một tình huống khác trong đó độ dài đầu ra chính xác là khi văn bản nén được mã hóa: khi đối thủ có thể gửi một phần văn bản được nén và mã hóa, các biến thể về độ dài của bản mã có thể tiết lộ phần văn bản được nén và mã hóa Kẻ thù; Khai thác CRIME trên HTTPS .