如何查网站空间,网页在线制作网站源码,wordpress怎么增加菜单,常用网站建设工具阿拉伯数字与中文数字没有一一对应关系#xff0c;不存在直接转换的公式化算法#xff0c;因此需要根据两种数字体系的特点精心构造转换算法。中文计数有一个特点#xff0c;就是“零”的使用变化多端。阿拉伯数字中数字的权位依靠数字在整个数字长度中的偏移位置确定#…阿拉伯数字与中文数字没有一一对应关系不存在直接转换的公式化算法因此需要根据两种数字体系的特点精心构造转换算法。中文计数有一个特点就是“零”的使用变化多端。阿拉伯数字中数字的权位依靠数字在整个数字长度中的偏移位置确定因此数字中间出现的0用于标记数字的偏移位置即便是连续出现的0也不能省略。中文计数方式中每个数字的权位都直接跟在数字后面因此代表连续出现的若干个0。尽管如此也不是所有的情况都使用“零”比如阿拉伯数字 20001234中文数字表示为“二千万一千二百三十四”没有用一个“零”再比如阿拉伯数字 12000中文数字表示为“一万二千”也没有用“零”但是对于阿拉伯数字 10210300中文数字表示为“一千零二十一万零三百”两次出现“零”。针对这种情况中文数字对“零”的使用总结起来有以下三条规则以 10000 为小节小节的结尾即使是 0也不使用“零”。小节内两个非 0 数字之间要使用“零”。当小节的“千”位是 0 时若本小节的前一小节无其他数字则不用“零”否则就要用“零”。从阿拉伯数字到中文数字的转换第一步是以“万”为单位分节并确定节权位。第二步是对每小节内的数字确定权位并按照前面的三种方法处理“零”的问题一个转换示例以阿拉伯数字 200001010200 为例首先以“万”为单位对其分节可分为三节2000 0101 0200:第一节 2000节权位是“亿”因为这一节的 0 都在结尾根据规则 1此处不使用“零”直接表示为“二千亿”。第二节 0101节权位是“万”因两个 1 之间有 0根据规则 2101 可以描述为“一百零一”。另外此节的千位是 0根据规则 3因本小节前还有数字因此需要用“零”。也就是说本小节需要两个“零”。最后一个小节结尾的两个 0 根据规则 1不使用“零”但是千位的 0 根据规则 3需要使用“零”。根据以上分析将三个小节的转换结果组合在一起阿拉伯数字 200001010200 的中文表示就是“二千亿零一百零一万零二百”。从这个例子可以看出来对阿拉伯数字分节确定数字的权位很简单最难处理的就是 0 的转换需要根据三个规则灵活选择是否需要使用“零”。转换算法设计设计阿拉伯数字转中文数字的算法也可以遵循上例中的两个步骤来处理但是需要解决三个问题。第一个问题是单个数字的转换这个并不难因为阿拉伯数字 0〜9 与相应的中文数字是一一对应的。对这个转换设计算法非常简单可以定义中文数字表const char *chnNumChar[CHN_NUM_CHAR_COUNT] {零,一,二,三,四,五,六,七,八,九};待转换的阿拉伯数字作为const char *chnUnitSection[] {万,亿,万亿};对于 32 位正数能表达的最大数来说最大节权是“万亿”己经足够了如果要转换更大的数可以延伸这个节权表的定义比如增加“亿亿”。数字中最低的节没有节权使用空字符const char *chnUnitChar[] {十,百,千};最低位的权位是空字符串处理方式和节权位的处理方式一样。数字权位的确定并不困难通过移位就可以确定每个数字对应的权位。阿拉伯数字的权位是隐含在数字的位数中的使用 0 作为占位符。比如数字 1000要使1处在千位一定会补 3 个 0 作为占位符否则1就不代表“一千”。既然每一位的权都在固定的位置上只要记录移位的次数就可以确定阿拉伯数字的权位以移位次数做下标直接查 chnUnitSection 和 chnUnitChar 表就可以得到正确的中文数字的权位。第三个需要解决的问题是如何处理中文“零”。这个问题稍微有点困难需要根据文章开头给出的三个规则灵活判断此外对于连续出现的阿拉伯数字 0也只能用一个中文“零”。算法实现转换算法首先要对阿拉伯数字分节并确定节权位名称。num 对 10000 取模可得到一个 section将这个 section 转成中文数字然后根据节的位置补上节权位即可完成一个节的中文数字转换。重复这个过程直到 num 等于 0 为止整个转换就算完成。unitPos 变量记录节的位置0 对应空字符串1 对应“万”2 对应“亿”随着 unitPos 的增加节权位也越来越大。全 0 的节不需要节权位这个在代码中也有处理。根据规则 3 的定义如果一节内数字的千位是 0需要根据前面是否还有数字决定是否需要加“零”NumberToChinese() 函数中利用变量 needZero 和 while(num 0) 循环语句巧妙地做了这个加“零”处理省去了一个if判断。//num 0需要特殊处理直接返回零void NumberToChinese(unsigned int num, std::string chnStr){int unitPos 0;std::string strIns;bool needZero false;while(num 0){unsigned int section num % 10000;if(needZero){chnStr.insert(0, chnNumChar[0])}SectionToChinese(section, strIns);/*是否需要节权位 */strIns (section ! 0) ? chnUnitSection[unitPos] : chnUnitSection[0];chnStr.insert(0, strIns);/*千位是0需要在下一个section补零*/needZero (section 1000) (section 0);num num / 10000;unitPos;}}SectionToChinese() 函数将一个节的数字转换成中文数字利用中文数字表 chnNumChar 转换中文数字利用表 chnUnitChar 得到数字权位unitPos 变量用作权位索引。SectionToChinese() 函数的关键部分是对 0 的处理根据规则 1 和规则 2小节结尾的 0 不需要转换成“零”但是两个数字之间的 0 需要转换成“零”。如果两个数字之间有 多个 0也只转换一个“零”变量 zero 用于控制“零”的转换避免出现多个“零”连在一起的情况。void SectionToChinese(unsigned int section, std::string chnStr){std::string strIns;int unitPos 0;bool zero true;while(section 0){int v section % 10;if(v 0){if( (section 0) || Izero ){zero true; /*需要补zero的作用是确保对连续的多个只补一个中文零*/chnStr.insert(0, chnNumChar[v]);}}else{zero false; //至少有一个数字不是strIns chnNumChar[v]; //此位对应的中文数字strIns chnUnitChar [unitPos]; //此位对应的中文权位chnStr.insert(0, strIns);}unitPos; //移位section section / 10;}}中文大写数字中文数字还有一个很有意思的现象就是中文数字大写。所谓的大写其实就是用一些笔画复杂的汉字代替简单的数字汉字其目的就是为了保证其不容易被篡改。中文大写用“壹贰叁肆伍陆柒捌玫”代替“一二三四五六七八九”用“拾佰仟”代替“十百千”。这些数字的繁写其实在唐代就己经出现但正式作为记载钱粮、税收等项目用的官方数字是在明朝初年著名的“郭桓案”之后。郭桓案与空印案、胡惟庸案和蓝玉案一起并称为明初四大案。郭桓案发生在明朝洪武十八年(1385年)属于官吏贪污案件。户部侍郎郭桓等人串通地方官吏作弊篡改账册私吞太平、镇江等府的赋税还盗卖官粮。后被揭发以其涉案金额巨大对经济领域影响深远而为世人瞩目对此明太祖将六部左、右侍郎以下官员全部处死地方官吏死于狱中者达数万人以上。为了追赃牵连到全国各地的小富百姓遭到抄家破产的不计其数。由于牵扯面 广全国百姓对此案非常不满意明太祖为了平息民怨将审刑官吴席等人也一并处死。实现中文大写数字的转换只需要将 chnNumChar、chnUnitSection 中的中文数字和权位名称替换成大写数字就可以了转换算法是一样的。如果用于人民币记账可调整节权位的名称加上“圆”或“圆整”等权名有兴趣的读者可自行完成转换代码。