我有一个包含29个问题的调查,每个问题都有一个5分的李克特量表(0 =没有时间; 4 =大部分时间)。我想将一组响应压缩为少量的字母或字母数字字符,并在末尾添加一个校验位。
因此,响应集var result = RunCommand<SomeOtherType>(q => q.Where(x => ....).Select(x => ....));
将转变为类似00101244231023110242231421211
的内容。此输出将是非技术用户在网站上输入的打印输出的一部分,作为输入整个字符串的快捷方式。我想避免模糊的字符,例如A2CR7HW4
,让我使用21或22个字符(仅限大写)。或者,我可以只使用大写字母,并使用全部26个字符。
我正在考虑将每对数字转换成一个字母(5 ^ 2 = 25,因此整个字母表就足够了)。这会将序列减少到15个字符,这仍然很长,无错误地输入。
关于如何最小化输出长度的任何其他建议?
编辑:BTW,就上下文而言,该调查询问了29个关于精神健康症状的问题,为4种精神疾病产生了预测风险。需要一个代表所有回复的代码。答案 0 :(得分:2)
如果五个答案都具有相同的可能性,那么您可以做的最好的是ceiling(29 * log(5) / log(n))
个符号,其中n
是字母表中符号的数量。 (对数的基数并不重要,只要它们都是相同的。)
因此对于你的22个符号,你能做的最好的是16个。对于26个符号,最好的是15,如你所描述的25个。如果你使用49个字符(例如大写和小写字符的某个子集和数字),你可以降到12.你可以使用可打印的ASCII字符最好的是11,使用94个字符中的70个。
使其变小的唯一方法是,如果响应不同样可能并且严重偏斜。虽然如果是这样的话,那么调查可能有些不对劲。
答案 1 :(得分:1)
首先,选择一组允许的字符,即
characters = "ABC..."
然后,在输入数字前加1,并将其解释为一个五进制数:
100101244231023110242231421211
现在,将此序号转换为基数 - &#34; strlen(字符)&#34;,即如果要使用26个字符,则为base26:
02 23 18 12 10 24 04 19 00 15 14 20 00 03 17
然后,在&#34;字符&#34;中使用这些数字作为索引,您就拥有了编码:
CVSMKWETAPOUADR
对于解码,只需颠倒步骤即可。
答案 2 :(得分:0)
你是用特定语言做的吗?
如果您想要真正节俭,可能需要考虑在位级编码数据。
由于每个问题只有5个可能的答案,因此只需3位即可:
000
001
010
011
100
您的最终结果将是一串位,每个答案为3位,因此总共87位或10位和一位字节。
编辑 - 稍微误读了这个问题,有5个可能的答案不是4,我的错误。
现在唯一的问题是,对于你的5个答案中的4个,你会浪费一点......你不会因为遇到这么多麻烦而受益匪浅,我不会说但是值得考虑。
编辑:
我一直在玩它,并且很难找到一种允许你同时使用2位和3位值的机制。
由于您的输出是97位二进制值,因此在转换回原始值时,您需要能够区分2到3位值。
如果您正在使用大量值,则可以使用一些方法,例如为每个值设置一个保留位,可用于对值进行排序并赋予其一些含义。但是如果处理这么少的东西,就很难剃掉任何东西。
您的97位输出可以填充为128位,如果您想简化它,将为您提供4个32位值。这个128位值就像一个代表一组特定答案的唯一指纹。有很多方法可以代表128位。
但最终在位级别的borking与实际压缩和数据编码一样好...如果你能在不到3位中表达5个唯一值,我会给你留下深刻的印象