如何压缩仅包含 "F" 和 "G" 的 256 字节字符串?
How would you compress 256-byte string consists of only "F" and "G"?
理论上,您可以将这个仅包含 "F" 和 "G" 的 256 字节字符串压缩多少?
FGFFFFFFGFFFFGGGGGGGGGGGGGFFFFFGGGGGGGGGGGGFFGFGGGFFFGGGGGGGGFFFFFFFFFFFFFFFFFFFFFGGGGGGFFFGFGGFGFFFFGFFGFGGFFFGFGGFGFFFGFGGGGFGGGGGGGGGFFFFFFFFGGGGGGGFFFFFGFFGGGGGGGFFFGGGFFGGGGGGFFGGGGGGGGGFFGFFGFGFFGFFGFFFFGGGGFGGFGGGFFFGGGFFFGGGFFGGFFGGGGFFGFGGFFFGFGGF
虽然我没有看到真实世界的应用程序,但有趣的是 gz、bzip2 和 deflate 等压缩算法在这种情况下有一个缺点。
好吧,我有这个答案和要演示的 C# 代码:
using System;
public class Program
{
public static void Main()
{
string testCase = "FGFFFFFFGFFFFGGGGGGGGGGGGGFFFFFGGGGGGGGGGGGFFGFGGGFFFGGGGGGGGFFFFFFFFFFFFFFFFFFFFFGGGGGGFFFGFGGFGFFFFGFFGFGGFFFGFGGFGFFFGFGGGGFGGGGGGGGGFFFFFFFFGGGGGGGFFFFFGFFGGGGGGGFFFGGGFFGGGGGGFFGGGGGGGGGFFGFFGFGFFGFFGFFFFGGGGFGGFGGGFFFGGGFFFGGGFFGGFFGGGGFFGFGGFFFGFGGF";
uint[] G = new uint[8]; // 256 bit
for (int i = 0; i < testCase.Length; i++)
G[(i / 32)] += (uint)(((testCase[i] & 1)) << (i % 32));
for (int i = 0; i < 8; i++)
Console.WriteLine(G[i]);
string gTestCase = string.Empty;
//G 71 0100 0111
//F 70 0100 0110
for (int i = 0; i < 256; i++)
gTestCase += (char)((((uint)G[i / 32] & (1 << (i % 32))) >> (i % 32)) | 70);
Console.WriteLine(testCase);
Console.WriteLine(gTestCase);
if (testCase == gTestCase)
Console.WriteLine("OK.");
}
}
听起来可能很傻,但至于我如何改进算法,使这个256位的十进制数可以进一步压缩,我有以下想法:
(注:以下是不同的讨论主题,但与进一步压缩256字节有关)
根据我对微软实现Decimal
、
的理解
96-bit + 96-bit = 128-bit decimal.
这意味着包含任意两个不同字符的 192 字节字符串可以编码为 128 位数字而不是 192 位数字。正确吗?
我的问题是:
我可以用 256 字节的字符串做同样的事情吗?
(通过将它们中的每一个分成一对两个数字,然后将这两个数字相加为 Decimal
短于 256 位)?
如何将上述128位Decimal
解码回一对两个96位数字,同时保持压缩数据大小小于 192 位?
抱歉我之前的问题比较含糊。
以下代码将演示如何将两个 96 个字符的 "binary" 字符串添加为 128 个字符的二进制字符串。
public static string AddBinary(string a, string b) // 96-char binary strings
{
int[] x = { 0, 0, 0 };
int[] y = { 0, 0, 0 };
string c = String.Empty;
for (int z = 0; z < a.Length; z++)
x[(z / 32)] |= ((byte)(a[a.Length - z - 1]) & 1) << (z % 32);
for (int z = 0; z < b.Length; z++)
y[(z / 32)] |= ((byte)(b[b.Length - z - 1]) & 1) << (z % 32);
decimal m = new decimal(x[0], x[1], x[2], false, 0); //96-bit
decimal n = new decimal(y[0], y[1], y[2], false, 0); //96-bit
decimal k = decimal.Add(m, n);
int[] l = decimal.GetBits(k); //128-bit
Console.WriteLine(k);
for (int z = 127; z >= 0; z--)
c += (char)(((l[(z / 32)] & (1 << (z % 32))) >> (z % 32)) | 48);
return c.Contains("1") ? c.TrimStart('0') : "0";
}
96-bit + 96-bit = 128-bit decimal.
这是误会。 Decimal
是96bit的integer/mantissa,一个符号和一个0到28(~5bit)的指数构成比例因子尾数。
加法是从2×(1+5+96)位到1×(1+5+96)位,包括不可避免的舍入误差和溢出。
您不能轻易地从求和中得到加数 - 对于初学者来说,加法是对称的,没有任何地球上的方法可以知道两个加数中哪个是第一个,哪个是第二个。
mentioned the programmer's variant of compressibility: Kolmogorov complexity.
平心而论,您必须将输入字符串的 重新编码 的 256 位添加程序的大小,才能将这些位转换为原始字符串。
(与 gz、bzip2、deflate(、LZW) - decoders for "pure LZ" can be very small. The usual escape is to define a file format 一样,包括可识别的 header。)
mentioned one consequence of the Pigeon-hole principle:要区分每一个192位的组合,你需要不少于2^192个代码。
理论上,您可以将这个仅包含 "F" 和 "G" 的 256 字节字符串压缩多少?
FGFFFFFFGFFFFGGGGGGGGGGGGGFFFFFGGGGGGGGGGGGFFGFGGGFFFGGGGGGGGFFFFFFFFFFFFFFFFFFFFFGGGGGGFFFGFGGFGFFFFGFFGFGGFFFGFGGFGFFFGFGGGGFGGGGGGGGGFFFFFFFFGGGGGGGFFFFFGFFGGGGGGGFFFGGGFFGGGGGGFFGGGGGGGGGFFGFFGFGFFGFFGFFFFGGGGFGGFGGGFFFGGGFFFGGGFFGGFFGGGGFFGFGGFFFGFGGF
虽然我没有看到真实世界的应用程序,但有趣的是 gz、bzip2 和 deflate 等压缩算法在这种情况下有一个缺点。
好吧,我有这个答案和要演示的 C# 代码:
using System;
public class Program
{
public static void Main()
{
string testCase = "FGFFFFFFGFFFFGGGGGGGGGGGGGFFFFFGGGGGGGGGGGGFFGFGGGFFFGGGGGGGGFFFFFFFFFFFFFFFFFFFFFGGGGGGFFFGFGGFGFFFFGFFGFGGFFFGFGGFGFFFGFGGGGFGGGGGGGGGFFFFFFFFGGGGGGGFFFFFGFFGGGGGGGFFFGGGFFGGGGGGFFGGGGGGGGGFFGFFGFGFFGFFGFFFFGGGGFGGFGGGFFFGGGFFFGGGFFGGFFGGGGFFGFGGFFFGFGGF";
uint[] G = new uint[8]; // 256 bit
for (int i = 0; i < testCase.Length; i++)
G[(i / 32)] += (uint)(((testCase[i] & 1)) << (i % 32));
for (int i = 0; i < 8; i++)
Console.WriteLine(G[i]);
string gTestCase = string.Empty;
//G 71 0100 0111
//F 70 0100 0110
for (int i = 0; i < 256; i++)
gTestCase += (char)((((uint)G[i / 32] & (1 << (i % 32))) >> (i % 32)) | 70);
Console.WriteLine(testCase);
Console.WriteLine(gTestCase);
if (testCase == gTestCase)
Console.WriteLine("OK.");
}
}
听起来可能很傻,但至于我如何改进算法,使这个256位的十进制数可以进一步压缩,我有以下想法:
(注:以下是不同的讨论主题,但与进一步压缩256字节有关)
根据我对微软实现Decimal
、
96-bit + 96-bit = 128-bit decimal.
这意味着包含任意两个不同字符的 192 字节字符串可以编码为 128 位数字而不是 192 位数字。正确吗?
我的问题是:
我可以用 256 字节的字符串做同样的事情吗?
(通过将它们中的每一个分成一对两个数字,然后将这两个数字相加为Decimal
短于 256 位)?如何将上述128位
Decimal
解码回一对两个96位数字,同时保持压缩数据大小小于 192 位?
抱歉我之前的问题比较含糊。
以下代码将演示如何将两个 96 个字符的 "binary" 字符串添加为 128 个字符的二进制字符串。
public static string AddBinary(string a, string b) // 96-char binary strings
{
int[] x = { 0, 0, 0 };
int[] y = { 0, 0, 0 };
string c = String.Empty;
for (int z = 0; z < a.Length; z++)
x[(z / 32)] |= ((byte)(a[a.Length - z - 1]) & 1) << (z % 32);
for (int z = 0; z < b.Length; z++)
y[(z / 32)] |= ((byte)(b[b.Length - z - 1]) & 1) << (z % 32);
decimal m = new decimal(x[0], x[1], x[2], false, 0); //96-bit
decimal n = new decimal(y[0], y[1], y[2], false, 0); //96-bit
decimal k = decimal.Add(m, n);
int[] l = decimal.GetBits(k); //128-bit
Console.WriteLine(k);
for (int z = 127; z >= 0; z--)
c += (char)(((l[(z / 32)] & (1 << (z % 32))) >> (z % 32)) | 48);
return c.Contains("1") ? c.TrimStart('0') : "0";
}
96-bit + 96-bit = 128-bit decimal.
这是误会。 Decimal
是96bit的integer/mantissa,一个符号和一个0到28(~5bit)的指数构成比例因子尾数。
加法是从2×(1+5+96)位到1×(1+5+96)位,包括不可避免的舍入误差和溢出。
您不能轻易地从求和中得到加数 - 对于初学者来说,加法是对称的,没有任何地球上的方法可以知道两个加数中哪个是第一个,哪个是第二个。
平心而论,您必须将输入字符串的 重新编码 的 256 位添加程序的大小,才能将这些位转换为原始字符串。
(与 gz、bzip2、deflate(、LZW) - decoders for "pure LZ" can be very small. The usual escape is to define a file format 一样,包括可识别的 header。)