跪求数字压缩算法

铁锚
博客专家认证
2013-11-06 06:01:18
背景:
身份证号码的前17位,是数字类型的字符串:比如"53010119870615158",现在书写的时候占了17个字符,有没有办法将其压缩短一些,比如,10位之类的。

需求:
1. 可以采用十六进制,或者10进制,或者 数字和字母的组合
2. 不易区分的数字字母除外,比如: I 和 1, O 和 0 .
3. 需要生成的新字符,可以转换为原来的值(即无损).
4. 需要有稳定的生成的位数,可以在最开始补0之类的。
请各位大神提供解决方案,或者思路,或者链接都可以。
...全文
828 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
Wei_An 2014-05-09
  • 打赏
  • 举报
回复
我的简陋思路:查表法 原理:因为身份证号码都有特殊的含义,例如行政区域,可以用查表法来进行字符串转换数字数组,对栈内存消耗减少,然后再结合以上的高手思路,或者会更加好。 个人愚见,仅供参考,谢谢!
cnmhx 2013-11-09
  • 打赏
  • 举报
回复
自然地使用阿斯克码,2^8=256,相当于256进制。 身份证的17位事实上是16位(没有人的岁数超过999岁)。 这样10^16约为2^48,即使用6个256进制的阿斯克码足矣!
nice_cxf 2013-11-08
  • 打赏
  • 举报
回复
直接用long long当数字存就ok了,8字节就够了,还想小的话要细分行政区域出生日期等,也许可以再少点,不过大概也省不了多少了
hello_world_ww 2013-11-07
  • 打赏
  • 举报
回复
1.转换为高进制是个不错的思路,但是理论上讲即使100进制也只会将10进制数的串长度减半,所以需要考虑其他办法 2.把17为的身份证号码中间截断为8+9的形式,当做两个unsigined int类型的数按二进制形式写入文件,只需要2*4 bytes,相比于字符串存储的17bytes,压缩率超过50% 再想……
O西瓜 2013-11-06
  • 打赏
  • 举报
回复
16进制从0至f用每一个字符代表值,当10进制的17位数转成16位时,可以缩短到12位,你可以从0至z的这些字符都用上,扩展到26进制,也可以把ascii的字符包括进来,40进制都没问题,只要是一个单独的字符都可以用上。
还有多远 2013-11-06
  • 打赏
  • 举报
回复
提供个思路,仅供参考: (1)17位身份证号末位(最右边一位)可能是X,可以保留不进行处理 (2)由于36*36 = 1296 > 1000,所以我们可以用一个36进制的两位数(最大是1295)完全表示一个10进制的3位数(最大是999),这样,我们可以把17位身份证的前15位压缩成10位(每三位压缩成两位),再直接拼接上身份证号的后2位,就成了一个12位的固定长度的身份证号(当然也可以再以某种方式处理后两位,使之变成一位) (3)设计一个36进制,例如0~9a~z,这样的话,就可以写出如下的转换:

string compressId(const string& id)
{
    int num, i, k = 0, tmp;
    string compressed(12, ' ');//预留12个字符的空间
    for(i = 0; i < 15; i += 3){
        num = (id[i]-'0')*100 + (id[i+1]-'0')*10 + (id[i+2]-'0');
        tmp = num/36; 
        num %= 36;
        compressed[k++] = tmp > 9 ? tmp-10+'a' : tmp+'0';//36进制数的高位
        compressed[k++] = num > 9 ? num-10+'a' : num+'0';//36进制数的低位
    }
    compressed[10] = id[15];
    compressed[11] = id[16];
    return compressed;
}
string retrieveId(const string& compressed)
{
    int num, i, k = 0;
    string id(17, ' ');//预留17个字符的空间
    for(i = 0; i < 10; i += 2){
        num = (compressed[i] > '9' ? compressed[i]-'a'+10 : compressed[i]-'0') * 36 +
              (compressed[i+1] > '9' ? compressed[i+1]-'a'+10 : compressed[i+1]-'0');
        id[k++] = num/100 + '0';//10进制数的百位
        num %= 100;
        id[k++] = num/10 + '0';//10进制数的十位
        num %= 10;
        id[k++] = num + '0';//10进制数的个位
    }
    id[15] = compressed[10];
    id[16] = compressed[11];
    return id;
}
我也很迷茫 2013-11-06
  • 打赏
  • 举报
回复
530101198706015158 我提供一个思路吧.身份证号至少可以分成这三节. 第一节表示一个地址. 第二节表示出生日期. 第三节表示顺序号和男女性别. 我只从出生日期上来考虑. 假设你的系统能运行到2100年. 那么你的系统里人的出生年份将是[1900, 2100]这个区间. 200年而已. 将十进制的200先转为二进制. 再将二进制转为十六进制. 我们知道, 2的8次方是256, 怎么样够了吧. 也就是说, 用16进制的00~FF就可以表示1900~2100年的所有年份了. 还有剩余! 这样, 本来四位年份就变成了两位了对不对~ 我们再继续. 月份, 一年只有12个月. 用一个十六进制就搞定了.又省了一位对不对~ 日期, 最多31. 如果16进制也要两位. 好了. 然后你再去想办法搞到地址对应的身份证前6位. 肯定可以减少的. PS. 以上我是在16进制的范畴下讨论的. 如果你胆子更大一点, 完全可以用更大的进制! 0~9 A~Z a~z可用的进制大的很呢~ 16进制只是其中很小的一份. 再PS. 以上讨论是基于新身份证号的. 现在还有老身份证号. 需要一个额外的位置, 表示这是新的身份证还是老的身份证

33,007

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧