惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

A
About on SuperTechFans
Y
Y Combinator Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Microsoft Security Blog
Microsoft Security Blog
aimingoo的专栏
aimingoo的专栏
I
InfoQ
C
Check Point Blog
IT之家
IT之家
MyScale Blog
MyScale Blog
Apple Machine Learning Research
Apple Machine Learning Research
Vercel News
Vercel News
Last Week in AI
Last Week in AI
GbyAI
GbyAI
P
Proofpoint News Feed
量子位
Stack Overflow Blog
Stack Overflow Blog
Microsoft Azure Blog
Microsoft Azure Blog
月光博客
月光博客
阮一峰的网络日志
阮一峰的网络日志
人人都是产品经理
人人都是产品经理
B
Blog
T
The Blog of Author Tim Ferriss
H
Help Net Security
云风的 BLOG
云风的 BLOG

博客园 - 银河

表示无向图的的数据类型 计算幂函数的几种方法 浅谈浮点数运算的误差 浅谈 System.Decimal 结构 两种计算自然对数的算法比较 计算自然对数的算法 计算指数函数的算法 计算自然对数的快速算法 第N个素数的渐近公式 浅谈 System.Linq.Enumerable.AsEnumerable 方法 在键值表中寻找最大值的键 浅谈中日韩越统一表意文字 浅谈 GB13000 统计中文文本中常用字占比 随机生成常用汉字(改进版) 谈谈 .NET Reflector 现代汉语常用字与国标一级字的比较 微软的必应搜索引擎出现故障 绝妙的取样
随机生成常用汉字(再次改进版)
银河 · 2012-12-22 · via 博客园 - 银河

引言

两个月前我写了一篇随笔“随机生成常用汉字”,生成汉字的来源是国标(GB2312)一级字(共3755字)。

昨天我写了一篇随笔“随机生成常用汉字(改进版)”,生成汉字的来源增加了现代汉语常用字(共3500字)。

园友评论说:

  • 菜菜灰 园友:也有很多不认识的,用户体验不好
  • 新的开始 园友:也可以用在生成验证码上的,那就需要是大部分人都认识的字了

我们知道,现代汉语常用字(共3500字)分为常用字(共2500字)和次常用字(共1000字)。为此,我们就需要再次改进随机生成常用汉字的程序,生成汉字的来源增加现代汉语常用字中的常用字(共2500字)。

随机生成常用汉字的 C# 程序(再次改进版)

在前面几篇随笔的基础上,很容易写出再次改进后的随机生成常用汉字的 C# 程序。

首先是独立出来的 RandomChinese 类,如下所示:

  1 using System;
  2 using System.Text;
  3 using System.Linq;
  4 using System.ComponentModel;
  5 using System.Collections.Generic;
  6 
  7 namespace Skyiv
  8 {
  9   public sealed class RandomChinese
 10   {
 11     public enum Source { From2500, From3500, From3755 }
 12 
 13     char[] source;
 14     int sourceLength;
 15     Random random;
 16 
 17     public RandomChinese(Source source, int? seed = null)
 18     {
 19       switch (source)
 20       {
 21         case Source.From2500: this.source = GetChinese2500().ToArray(); break;
 22         case Source.From3500: this.source = GetChinese3500().ToArray(); break;
 23         case Source.From3755: this.source = GetGB2312String().ToArray(); break;
 24         default: throw new InvalidEnumArgumentException("source", (int)source, source.GetType());
 25       }
 26       sourceLength = this.source.Length;
 27       random = seed.HasValue ? new Random(seed.Value) : new Random();
 28     }
 29 
 30     public string GetSource()
 31     {
 32       return new string(source);
 33     }
 34 
 35     public string GetString(int count)
 36     {
 37       var sb = new StringBuilder(count);
 38       while (count-- > 0) sb.Append(source[random.Next(sourceLength)]);
 39       return sb.ToString();
 40     }
 41 
 42     // 现代汉语常用字中的常用字(共2500个)
 43     HashSet<char> GetChinese2500()
 44     {
 45       var set = GetChinese3500();
 46       set.ExceptWith("匕刁丐歹戈夭仑讥冗邓艾夯凸卢叭叽皿凹囚矢乍尔冯玄邦迂邢芋芍吏夷吁吕吆" +
 47         "屹廷迄臼仲伦伊肋旭匈凫妆亥汛讳讶讹讼诀弛阱驮驯纫玖玛韧抠扼汞扳抡坎坞抑拟抒芙芜苇芥芯芭杖杉巫" +
 48         "杈甫匣轩卤肖吱吠呕呐吟呛吻吭邑囤吮岖牡佑佃伺囱肛肘甸狈鸠彤灸刨庇吝庐闰兑灼沐沛汰沥沦汹沧沪忱" +
 49         "诅诈罕屁坠妓姊妒纬玫卦坷坯拓坪坤拄拧拂拙拇拗茉昔苛苫苟苞茁苔枉枢枚枫杭郁矾奈奄殴歧卓昙哎咕呵" +
 50         "咙呻咒咆咖帕账贬贮氛秉岳侠侥侣侈卑刽刹肴觅忿瓮肮肪狞庞疟疙疚卒氓炬沽沮泣泞泌沼怔怯宠宛衩祈诡" +
 51         "帚屉弧弥陋陌函姆虱叁绅驹绊绎契贰玷玲珊拭拷拱挟垢垛拯荆茸茬荚茵茴荞荠荤荧荔栈柑栅柠枷勃柬砂泵" +
 52         "砚鸥轴韭虐昧盹咧昵昭盅勋哆咪哟幽钙钝钠钦钧钮毡氢秕俏俄俐侯徊衍胚胧胎狰饵峦奕咨飒闺闽籽娄烁炫" +
 53         "洼柒涎洛恃恍恬恤宦诫诬祠诲屏屎逊陨姚娜蚤骇耘耙秦匿埂捂捍袁捌挫挚捣捅埃耿聂荸莽莱莉莹莺梆栖桦" +
 54         "栓桅桩贾酌砸砰砾殉逞哮唠哺剔蚌蚜畔蚣蚪蚓哩圃鸯唁哼唆峭唧峻赂赃钾铆氨秫笆俺赁倔殷耸舀豺豹颁胯" +
 55         "胰脐脓逛卿鸵鸳馁凌凄衷郭斋疹紊瓷羔烙浦涡涣涤涧涕涩悍悯窍诺诽袒谆祟恕娩骏琐麸琉琅措捺捶赦埠捻" +
 56         "掐掂掖掷掸掺勘聊娶菱菲萎菩萤乾萧萨菇彬梗梧梭曹酝酗厢硅硕奢盔匾颅彪眶晤曼晦冕啡畦趾啃蛆蚯蛉蛀" +
 57         "唬啰唾啤啥啸崎逻崔崩婴赊铐铛铝铡铣铭矫秸秽笙笤偎傀躯兜衅徘徙舶舷舵敛翎脯逸凰猖祭烹庶庵痊阎阐" +
 58         "眷焊焕鸿涯淑淌淮淆渊淫淳淤淀涮涵惦悴惋寂窒谍谐裆袱祷谒谓谚尉堕隅婉颇绰绷综绽缀巢琳琢琼揍堰揩" +
 59         "揽揖彭揣搀搓壹搔葫募蒋蒂韩棱椰焚椎棺榔椭粟棘酣酥硝硫颊雳翘凿棠晰鼎喳遏晾畴跋跛蛔蜒蛤鹃喻啼喧" +
 60         "嵌赋赎赐锉锌甥掰氮氯黍筏牍粤逾腌腋腕猩猬惫敦痘痢痪竣翔奠遂焙滞湘渤渺溃溅湃愕惶寓窖窘雇谤犀隘" +
 61         "媒媚婿缅缆缔缕骚瑟鹉瑰搪聘斟靴靶蓖蒿蒲蓉楔椿楷榄楞楣酪碘硼碉辐辑频睹睦瞄嗜嗦暇畸跷跺蜈蜗蜕蛹" +
 62         "嗅嗡嗤署蜀幌锚锥锨锭锰稚颓筷魁衙腻腮腺鹏肄猿颖煞雏馍馏禀痹廓痴靖誊漓溢溯溶滓溺寞窥窟寝褂裸谬" +
 63         "媳嫉缚缤剿赘熬赫蔫摹蔓蔗蔼熙蔚兢榛榕酵碟碴碱碳辕辖雌墅嘁踊蝉嘀幔镀舔熏箍箕箫舆僧孵瘩瘟彰粹漱" +
 64         "漩漾慷寡寥谭褐褪隧嫡缨撵撩撮撬擒墩撰鞍蕊蕴樊樟橄敷豌醇磕磅碾憋嘶嘲嘹蝠蝎蝌蝗蝙嘿幢镊镐稽篓膘" +
 65         "鲤鲫褒瘪瘤瘫凛澎潭潦澳潘澈澜澄憔懊憎翩褥谴鹤憨履嬉豫缭撼擂擅蕾薛薇擎翰噩橱橙瓢蟥霍霎辙冀踱蹂" +
 66         "蟆螃螟噪鹦黔穆篡篷篙篱儒膳鲸瘾瘸糙燎濒憾懈窿缰壕藐檬檐檩檀礁磷瞭瞬瞳瞪曙蹋蟋蟀嚎赡镣魏簇儡徽" +
 67         "爵朦臊鳄糜癌懦豁臀藕藤瞻嚣鳍癞瀑襟璧戳攒孽蘑藻鳖蹭蹬簸簿蟹靡癣羹鬓攘蠕巍鳞糯譬霹躏髓蘸镶瓤矗");
 68       return set;
 69     }
 70 
 71     // 现代汉语常用字(共3500个)
 72     HashSet<char> GetChinese3500()
 73     {
 74       var set = new HashSet<char>(GetGB2312String());
 75       set.ExceptWith("皑胺盎敖翱佰稗镑鲍钡苯甭迸毖敝陛卞斌摈炳钵铂箔帛蔡搽诧谗掣郴骋炽踌瞅躇滁" +
 76         "搐椽疵茨蹿瘁淬磋傣殆郸惮迪狄翟滇靛凋迭侗恫犊遁掇剁峨娥厄鄂洱珐藩钒酚汾烽氟涪弗釜腑阜讣噶" +
 77         "嘎赣皋铬庚龚蛊剐圭癸辊骸氦邯郝菏貉阂涸亨弘瑚桓豢磺簧卉烩姬缉汲蓟伎悸笺缄硷槛饯铰桔睫藉疥" +
 78         "靳烬粳痉炯厩咎狙疽咀踞娟撅攫抉浚郡喀咯亢柯侩匡岿奎馈婪阑谰佬镭磊傈涟撂廖霖拎羚陇掳麓潞禄" +
 79         "戮挛孪滦纶嘛谩卯酶镁寐醚幂抿牟氖淖妮霓倪拈啮镍涅哦沤啪琶磐耪呸裴抨砒琵毗痞瞥粕莆埔曝沏祁" +
 80         "讫扦钎仟堑羌蔷橇鞘沁氰邱酋泅龋颧醛炔榷冉壬妊戎茹孺汝阮鳃莎煽汕缮墒韶邵慑砷娠噬仕孰戍舜朔" +
 81         "嗣巳怂擞僳隋绥蓑獭挞酞坍绦锑嚏腆迢眺烃汀酮湍陀哇烷皖韦惟潍渭挝斡钨吾毋戊硒矽嘻烯汐檄襄霄" +
 82         "忻惺墟戌嘘眩绚丫焉阉彦佯疡瑶尧噎耶曳铱颐沂彝矣臆裔诣翌荫寅尹臃痈雍恿铀酉釉盂虞俞渝禹峪驭" +
 83         "垣苑曰郧匝哉札咋詹辗湛漳瘴肇蛰锗甄砧臻帧峙炙痔诌诛瞩拽篆兹淄孜渍鬃邹纂佐柞");
 84       set.UnionWith("叨蜓筝蜻橘匕丐夭叽吆凫阱芙杈岖鸠沐姊卦拗茉昙肴衩玷茴荞荠盹咧昵咪秕胧奕飒炫" +
 85         "祠荸莺桦唠蚣蚪蚓唧秫麸捺匾蚯蛉啰铐铛笙笤偎徙翎庵涮悴裆谒雳跛锉掰牍腌猬愕鹉蒿榄楣嗦跷蜈嗤" +
 86         "馍禀缤榛榕嘁嘀幔箫漩橄嘹蝠蝌蝙鲫憔翩嬉缭薇噩蟥霎踱蹂蟆螃鹦瘾缰檐檩瞭蟋蟀朦臊鳄鳍癞璧簸鬓躏");
 87       return set;
 88     }
 89     
 90     // 国标一级字(共3755个): 区:16-55, 位:01-94, 55区最后5位为空位
 91     string GetGB2312String()
 92     {
 93       var list = new List<byte>();
 94       for (var 区 = 16; 区 <= 55; 区++)
 95         for (int 位2 = (区 == 55) ? 89 : 94, 位 = 1; 位 <= 位2; 位++)
 96         {
 97           list.Add((byte)(区 + 0xa0));
 98           list.Add((byte)(位 + 0xa0));
 99         }
100       return Encoding.GetEncoding("GB2312").GetString(list.ToArray());
101     }
102   }
103 }

上述程序中:

  • 第90至101行的 GetGB2312String 方法生成3755个国标一级字。
  • 第71至88行的 GetChinese3500 方法生成3500个现代汉语常用字。该方法首先生成3755国标一级字,然后排除381个汉字,接着增加126个汉字。
  • 第42至69行的 GetChinese2500 方法生成2500个现代汉语常用字中的常用字。该方法首先生成3500个现代汉语常用字,接着排除1000个次常用字。
  • 第17至28行的构造函数根据 source 参数来决定调用上述三个方法之一。如果用在验证码等场合,就可以只调用一次构造函数,然后可以多次调用下面提到的 GetString 方法来生成随机汉字了,提高了效率。
  • 第24行处理传入的 source 参数不合法的情况,抛出 InvalidEnumArgumentException 异常。这可能发生在调用方使用以下语句:var rc = new RandomChinese((RandomChinese.Source)123); 时。
  • 第35至40行的 GetString 方法用于生成 count 个随机汉字。
  • 第30至33行的 GetSource 方法返回生成汉字的来源,即以下三者之一:3755个国标一级字、3500个现代汉语常用字、2500个现代汉语常用字中的常用字。

调用 RandomChinese 的示例程序

下面是 ChineseCreator.cs 源程序文件:

 1 using System;
 2 
 3 namespace Skyiv.Utils
 4 {
 5   static class ChineseCreator
 6   {
 7     static void Main(string[] args)
 8     {
 9       var count = (args.Length == 0) ? 500 : (args[0] == "all") ? -1 : int.Parse(args[0]);
10       var source = RandomChinese.Source.From2500;
11       if (args.Length > 1 && args[1] == "from3500") source = RandomChinese.Source.From3500;
12       if (args.Length > 1 && args[1] == "from3755") source = RandomChinese.Source.From3755;
13       var rc = new RandomChinese(source);
14       Console.WriteLine((count < 0) ? rc.GetSource() : rc.GetString(count));
15     }
16   }
17 }

这个示例程序简单地调用 RandomChinese 类的 GetString 方法来生成随机汉字。简要说明如下:

  • 第9行:该程序的第一个命令行参数(如果有的话)表示需要生成的汉字个数,默认是500个。如果该参数是 all,表示生成来源的全部汉字 。
  • 第10至12行:该程序的第二个命令行参数(如果有的话)表示所生成的汉字的来源,可能的值是:from3500、from3755,其他值表示现代汉语常用字的常用字。
  • 第13行:根据指定的生成汉字的来源,实例化一个 RandomChinese 类的实例。
  • 第14行:调用 RandomChinese 类的 GetString 方法生成随机汉字,或者 GetSource 方法生成全部汉字。

编译和运行

在 Arch Linux 的 Mono 2.10.8 环境下编译和运行:

work$ dmcs ChineseCreator.cs RandomChinese.cs
work$ mono ChineseCreator.exe 500 from2500
宏温谅事灾盗踪笼景袋母唯盐悬眨锁充乱获谎饥雪算愁弱走闷君冒撤名根初牺酒飞可翅头孟险教挤宁复谷划敏议张栋至溪变雀表势数槐铁湾语筒音酱短粮疾若寺阔丘鹊竟刀轿泊什秘签剑朽初呜椒荣秒根例俯王陈吗并扯蜂挽侦科椅匪烧奥悔犬蕉液摆摊走赔梨孤抄住势蓝私馅滴廊面糟未猛虾侵激误享霉边枝膜鼻约强包嫌司奋袖脸灰咸观蹲铁拼惑融脸朵拳鞠钓肆描耗岁闻咽鸽绑像贴踪正恢筒霉穗耽梅奴撞剪佳捐脚抽晨标肠币实杏崭躺即枣稍桶踩坟勉算脂窝斜燥摇浇腹福捏课充谱跳疆伟限织喜怠闯锻学昏奔必防霉心社姐躁划按且供味释吧脚挥秤混允喷施楚括虎拥辽孤灌凭典夕叔慰港宋虫丝伏疑弓鸡橡驶乏苏食句竖育撕议躁轰调果竞梨痕大跑鼠腾劳悟蝴璃厨满甲算在拦寇隔衰投压航宝谋帮逐代般码菜怪字诊光醉夫忧吨驾于刻垒民志袖窜尸慨收狱相果衰封大恋茧隐捧掠训跪劣看便衰专近姻详雾拜棋喜折前勤血开歉胜龟卵袄给足乓拼付稼搞尼汇捏存绢仪艇棒瓜挪虚挨晨轨袍闲书洲当员牺授革管极止曾痕是性桂交伤毫政摆满酿垦献躁宜棍帅引青顾蚊怎毕润槐片摸朱贩舒禾恶揪俱佛色另软置汪矿距直喷孕兵抽怀贸慈挑忽带患誓翅唤隶驳替恶师橘何产垫两拐扒胸动抗卡骆嫩慢橡汪置废好察造鹿孟塞防触鸡补帆付任抵晴半祖迈薄犁惯节检绘妖
work$ mono ChineseCreator.exe 500 from3500
瘫诡且肴昨食巨僚设姻弧揩缘刷豪馒疲俄真幌颊翠码揽焊结耙欲淌谤顺划购奏儒原葬氧咬犯兢掏阅焦捧垮鱼杉轴窍平耽燃媚碗哩爸穷睛喘托帕渠虑刨晴茫囚单萤轻炸父可纬氛澎咨苏殃江窿脐韧佳店倘镶媚磅窿介土主三粮募碰缺揪翎远疹登汉垂侵钻讹壤娃广辞蒋簸眶胸刹雳蠢趁樟卒险扳髓状碴但驶善劈压辰凑橙秸关荠憎锦称昭竣珍尿兢真旨荞楼烈理枝桅匠澈绎梆额弦紧差撼杭视记闻哭短膘译庶早酥睡抛憋边誊茸达柄制笙幻茂卿演们橡燃椅掀蛹棉陵帮誊汇桌嫉飒哄今酱扣掠耻蛮屹鸟本奇款峰命己颗涎羔恢柄橱凡蝠窒莱囚竞恍厂纸去腰持澄纳顷岁邪恶该材洪拟苹西如岛诺辟鹿灸安灾荆桨辆杭逛佑蚯廉俗倘荚注基友薯缭添酣横阀氧提充忽漓手主轿凑狼妇凭糟董橡囱钢淘保策貌置兴尺颂姚嗽结驼佣叉存诡刹桐醒离话煤党损啡拉桑菇净方富跟绣蚕慷抛况醇挖满螟弃森光田笙灼唾膀冻肩斋龙仗昂勉恭安楚瘤力灼针快纷陷村是揩何核唠碳述除净焙辐素恬阀蕊导葬犀阁痪潦永认莉蝠畏美冈入应志典聚奄卸补疆装捅锌咆伐谐溉辛到娘宝搜函谜肪群砸兑脑笆裂漫燕康算盔齐柠磅麸挠垦们绅鱼楚蛛幸翰机檩杭憾婉膘瓮戏内荤捂匈蕉锨妨迅桑锅樊逝常蚜垒凄养蚜羡粮趴伶陵逊李匾涡岗锤唐甩栖察叠窟迎证哺除盐时行葱她逻靠穴萌幻坑能畔珍部促植
work$ mono ChineseCreator.exe 500 from3755
匣杯斤佳榆傣见止气各挫抓健龄边入坞淀望散哑许紫梢截娥网因拽仓斥脯土束虑猎邱七顶遍腿恿蚀筹景胯丛溜钱诌筑搞汾愧昼前绘蜀姚漏宁畏写虐檬蛊硷贡吃绅母见期细牲肉沙俏输文鹰敞办狞叛狡狂副肺埂淬距毛漠盘浪兼姻领颓窝泞惜秀弛喻孵首宜陕方痴媚搔脚犊滑姬纵猖在馏暇鲸踊撞硼宛溯巍离种听甭迁衔禽库坟坎不畴肝聪祭书墙丹褥贫艺骑饭绥价硝宵豌管姬己携漫霉迁逞樱爵间收汽订舜燎改疥黑痴碧撑反些牡恐铃茸米逛露谜郧歌颤凝斜原酪希驭中蜡苗持徘浚餐槽陷海她季乒煌危抠承筒怔耍属束楚麻景浩车惭奠才钓话瞒盐饺息弱内萎做径恿胖戚匣兄星网嚏贺帖掩哄誊萎死詹蚀为卫围澎忌相隅胸吴字沫掌黔窖吧嗣症讯来烤套书蒋历济壳脊圈轴瞬蔗拈翱苫巴嗅篱般姻爷戎帧烂联甭饼漳饥欧雍烂定藤哈掏箍微措趴冕觉婴哲晕峻屁扭钉及制网省积聂瞩葡肢朝倘长衫吠插漫技草签酬夯吕晦烘涛蕴吹盅盛由炉蚂稠业怯鲁锅隔陈冠辙娠什识宜昌福窗墩卑泻郎寓烧孙丫易愚蔡焰胡巍卯绦邓藏漓爪见揍蝴脯预砒惶鸯坪圣起蝇濒秆豫卸韧泰宗抗涕您逼侯芋弛重陀顽垂鹃稗倪砒藕荒锥晴目畴报揍演每遏盘辛碍咬恳婉狂茧荚燃季茫听熟绒戚宿轿挛塞仟蓖蒲避矩罪壤邀权闪荐赴屉饰侵扔冠叉氮耪甩爽脖增肢滚冷片靛出棱典怪痒痒浇吃劫盒矽母浆

上面的三次运行都随机生成500个汉字,分别来源于:

  1. 2500个现代汉语常用字中的常用字。
  2. 3500个现代汉语常用字。
  3. 3755个国标一级字。

看起来是不是第一次运行生成的汉字基本上都能认识呢?第二次和第三次运行的结果差别不大呢?

work$ mono ChineseCreator.exe all from2500
啊阿挨唉哀矮碍爱安按暗岸案昂袄傲奥扒吧八疤巴 ... 奏租足族祖阻组钻筝嘴醉最罪尊遵昨左蜓叨做作坐座
work$ mono ChineseCreator.exe all from3500
啊阿埃挨哎唉哀癌蔼矮艾碍爱隘鞍氨安俺按暗岸案 ... 足卒族祖诅阻组钻筝嘴醉最罪尊遵昨左蜓叨做作坐座
work$ mono ChineseCreator.exe all from3755
啊阿埃挨哎唉哀皑癌蔼矮艾碍爱隘鞍氨安俺按暗岸 ... 足卒族祖诅阻组钻纂嘴醉最罪尊遵昨左佐柞做作坐座

上面三次运行分别生成了:

  1. 2500个现代汉语常用字中的常用字。
  2. 3500个现代汉语常用字。
  3. 3755个国标一级字。

参考资料

  1. 博客园: 随机生成常用汉字(改进版)
  2. 博客园: 随机生成常用汉字
  3. 博客园: 现代汉字常用字与国标一级字的比较
  4. 中国语言文字网: 《现代汉语常用字表》