阿拉伯数字与中文数字没有一一对应关系,不存在直接转换的公式化算法,因此需要根据两种数字体系的特点精心构造转换算法。

中文计数有一个特点,就是“零”的使用变化多端。阿拉伯数字中数字的权位依靠数字在整个数字长度中的偏移位置确定,因此数字中间出现的0用于标记数字的偏移位置,即便是连续出现的0也不能省略。中文计数方式中每个数字的权位都直接跟在数字后面,因此代表连续出现的若干个0。

尽管如此,也不是所有的情况都使用“零”,比如阿拉伯数字 20001234,中文数字表示为“二千万一千二百三十四”,没有用一个“零”;再比如阿拉伯数字 12000,中文数字表示为“一万二千”,也没有用“零”;但是对于阿拉伯数字 10210300,中文数字表示为“一千零二十一万零三百”,两次出现“零”。

针对这种情况,中文数字对“零”的使用总结起来有以下三条规则:

以 10000 为小节,小节的结尾即使是 0,也不使用“零”。

小节内两个非 0 数字之间要使用“零”。

当小节的“千”位是 0 时,若本小节的前一小节无其他数字,则不用“零”,否则就要用“零”。

从阿拉伯数字到中文数字的转换,第一步是以“万”为单位分节,并确定节权位。第二步是对每小节内的数字确定权位,并按照前面的三种方法处理“零”的问题:

一个转换示例

以阿拉伯数字 200001010200 为例,首先以“万”为单位对其分节,可分为三节:2000 0101 0200:

第一节 2000,节权位是“亿”,因为这一节的 0 都在结尾,根据规则 1,此处不使用“零”,直接表示为“二千亿”。

第二节 0101,节权位是“万”,因两个 1 之间有 0,根据规则 2,101 可以描述为“一百零一”。另外,此节的千位是 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 中的中文数字和权位名称替换成大写数字就可以了,转换算法是一样的。如果用于人民币记账,可调整节权位的名称,加上“圆”或“圆整”等权名,有兴趣的读者可自行完成转换代码。

大写汉字转阿拉伯数字c语言,阿拉伯数字转中文数字方法详解(C++实现)相关推荐

  1. C语言中宏定义使用方法详解

    C语言中的宏替换详解 首先看一个问题: #include <stdio.h> #define    PRINT_CLINE()    printf("%d", ____ ...

  2. 将阿拉伯数字转换为其对应的中文数字

    郑重声明,尽管这样子不文明,但还是先对这破电脑发泄发泄吧,不对人发泄就没有伤害! 妈蛋,这年头使用电脑太多,离开的电脑就是这么的个东西都写不出来了,真是丢人丢大了! 今天去面试,从市政府做的是8路公交 ...

  3. php读取字符阿拉伯数字,php 阿拉伯数字转中文数字 方法

    php 阿拉伯数字转中文数字 方法 function ch_num($num,$mode=true) { $char = array("零","壹"," ...

  4. c语言二级证题库及详解答案,全国计算机等级考试二级C语言上机题库及其答案详解...

    全国计算机等级考试二级C语言上机题库及其答案详解 全国计算机二级C语言上机考试题第一套给定程序的功能是:求二分之一的圆面积,函数通过形参得到圆的半径,函数返回二分之一的圆面积( 注: 圆面积公式为:2 ...

  5. R语言tidyr包gather()函数实战详解:数据收缩、从宽表到窄表

    R语言tidyr包gather()函数实战详解:数据收缩.从宽表到窄表 目录 R语言tidyr包gather()函数实战详解:数据收缩.从宽表到窄表 收缩两列数据

  6. R语言tidyr包spread()函数实战详解:数据裂变、从窄表到宽表

    R语言tidyr包spread()函数实战详解:数据裂变.从窄表到宽表 目录 R语言tidyr包spread()函数实战详解:数据裂变.从窄表到宽表

  7. R语言tidyr包Unite()函数实战详解:多个数据列合并为一列

    R语言tidyr包Unite()函数实战详解:多个数据列合并为一列 目录 R语言tidyr包Unite()函数实战详解:多个数据列合并为一列

  8. R语言tidyr包separate()函数实战详解:一列裂变为多列

    R语言tidyr包separate()函数实战详解:一列裂变为多列 目录 R语言tidyr包separate()函数实战详解:一列裂变为多列 一列裂变为两列

  9. c语言50到100套,c语言51-100套试题答案及详解.pdf

    c语言51-100套试题答案及详解 2 double ave=0.0; 第 51 套 试题答案及详解 3 *n=0; 4 for(i=0; i 5 ave /=N; /* 计算平均值 */ 一.程序填 ...

最新文章

  1. Docker学习(三)-----Docker镜像常用命令
  2. make: *** [ext/fileinfo/libmagic/apprentice.lo] Er
  3. 经济学人使用Golang构建微服务历程回顾
  4. Oracle imp字符集转换,imp/exp 字符集转换
  5. 使用ThreadLocal来解决问题
  6. docker启动后自动退出_Spring Boot项目启动后如何自动执行逻辑
  7. WTM框架使用技巧之:Layui版本嫁接Vue+ElementUI
  8. java怎么判断一个char是汉字_JAVA中判断char是否是中文的几种方法
  9. 京东物流将收购德邦股份66.49%股份
  10. 大数据全栈式开发语言 – Python
  11. crt导出服务器文件,非1元证书怎么提取生成crt文件
  12. 全球活跃开发者不足 1500 万,业余爱好者和学生仅占四分之一
  13. 关于might_sleep的一点说明
  14. winrar中文版去广告的方法,以winrar5.70简体中文版为例(其他版本也类似)
  15. python deap_在Python中用DEAP绘制多目标pareto边界
  16. 安装Microsoft Office Document Image Writer
  17. win7旗舰版怎么降级到专业版|win7旗舰版改成专业版的方法
  18. 网上赚钱怎么赚?锁定一个项目,才是赚钱的王道!
  19. C语言 模拟简单的地铁售票系统
  20. 【opencv】18、视频操作

热门文章

  1. 手把手教你D2C,走向前端智能化
  2. 2135亿!2018 双11阿里数据库技术战报新鲜出炉
  3. 西门子Mendix发低代码最新报告趋势:客户体验先行、智能化和全渠道化
  4. 有赞九周年,打造技术生态,与开发者一起投身新零售浪潮
  5. 梁胜:开源是最好的商业模式
  6. 稳居亚太第一,阿里云进军全球;李彦宏候选工程院院士;苹果巨大损失:工业设计核心元老纷纷离职……...
  7. IDC敲黑板啦:未来企业IT以混合云为主
  8. css让背景图片显示透明遮罩_CSS项目测试(支持深色模式)
  9. Elasticsearch7.15.2 分布式集群安装(linux环境)
  10. elasticsearch-head 谷歌插件以及安装和使用说明