常用算法实现(五)——python阿拉伯数字转中文
一.概述(阿拉伯数字转汉语数字)
在自然语言处理NLP任务中,阿拉伯数字转汉语数字是时常使用到的一个功能,但还是比较少的吧。
主要思想还是根据千兆、千亿、千万、千等单位三划分,依次按照权位转化。
github地址:
Tookit-Sihui/chinese_and_number.py at master · yongzhuo/Tookit-Sihui · GitHub
二.实现(常见模板生成句子)
实现的是: 支持小数,"."和点
# -*- coding: UTF-8 -*-
# !/usr/bin/python
# @time :2019/5/17 15:17
# @author :Mo
# @function :change chinese digit to Arab or reversedimport randomdef is_total_num(text):"""判断是否是数字的:param text: str:return: boolean, True or false"""try:text_clear = text.replace(" ", "").strip()number = 0for one in text_clear:if one.isdigit():number += 1if number == len(text_clear):return Trueelse:return Falseexcept:return False# chinese_to_number, 单位-数字
unit_dict = {"十": 10, "百": 100, "千": 1000, "万": 10000, "亿": 100000000,"拾":10, "佰":100, "陌":100, "仟":1000, "阡":1000, "萬":10000, "億":100000000}
unit_dict_keys = unit_dict.keys()
digit_dict = {"零": 0, "一": 1, "二": 2, "两": 2, "俩": 2, "三": 3,"四": 4, "五": 5, "六": 6, "七": 7, "八": 8, "九": 9,"壹":1, "贰":2, "叁":3, "肆":4, "伍":5, "陆":6, "柒":7, "捌":8, "玖":9, "弌":1, "弍":2, "弎":3,"貳":2, "陸":6, "0":0, "1":1, "2":2, "3":3, "4":4, "5":5, "6":6, "7":7, "8":8, "9":9}# number_to_chinese, 单位-数字
num_dict = { 0: "零", 1: "一", 2: "二", 3: "三", 4: "四",5: "五", 6: "六", 7: "七", 8: "八", 9: "九" }
unit_map = [ ["", "十", "百", "千"], ["万", "十万", "百万", "千万"],["亿", "十亿", "百亿", "千亿"], ["兆", "十兆", "百兆", "千兆"] ]
unit_step = ["万", "亿", "兆"]class chinese_to_number():def __init__(self):self.result = 0.0self.result_last = 0.0# 字符串分离self.str_billion = "" # 亿self.str_billion_hundred = "" # 亿万self.str_billion_one = ""self.str_thousand_ten = "" # 万self.str_single = "" # onedef free_zero_and_split_three_parts(self, text):"""去零切分成三部分:param text:str :return: """assert type(text) == str# if "零" in text:# text = text.replace("零", "")# 分切成三部分index = 0flag_billion = True # 亿flag_billion_hundred = True # 万亿flag_thousand_ten = True #万len_text = len(text)for i in range(len_text):if "亿" == text[i]:# 存在亿前面也有万的情况,小分节self.str_billion = text[0:i]if text.find("亿") > text.find("万"):for j in range(len(self.str_billion)):if "万" == self.str_billion[j]:flag_billion_hundred = Falseself.str_billion_hundred = self.str_billion[0:j]self.str_billion_one = self.str_billion[j+1:]# 如何亿字节中没有万,直接赋值if flag_billion_hundred:self.str_billion_one = self.str_billionindex = i + 1flag_billion = False# 分节完毕self.str_single = text[i + 1:]if "万" == text[i] and text.find("亿") < text.find("万"):self.str_thousand_ten = text[index:i]self.str_single = text[i+1:]flag_thousand_ten = Falseif flag_billion and flag_thousand_ten:self.str_single = textdef str_to_number(self, text):"""string change to number:param text: str:return: """assert type(text) == strnumber_res = 0number_1 = 0number_2 = 0number_3 = 0if not text:return 0len_text = len(text)# 规范语,for i in range(len_text):# 数字if text[i] in digit_dict:number_1 = digit_dict[text[i]]if i == len_text - 1: # 最后一个数字if len_text > 2: # 口语化的情形, 如一万五if text[len_text - 1] in digit_dict and text[len_text - 2] in unit_dict:number_res += number_1 * number_2 * 0.1breaknumber_res += number_1# 单位elif text[i] in unit_dict:number_2 = unit_dict[text[i]]if number_1==0 and number_2==10:number_3 = number_2else:number_3 = number_1 * number_2# 清零避免重复读取number_1 = 0number_res += number_3# 处理形如 "二点13亿", "1.56万" 这样的情况else:try:text_else_str = [str(digit_dict[tet]) if tet in digit_dict else tet for tet in text]number_res = float("".join(text_else_str))except:number_res = 0breakreturn number_resdef compose_integer(self, text):"""整数转数字, 合并:param text:str, input of chinese, eg.["一百", "三千零七十八亿三千零十五万零三百一十二"] :return: float, result of change chinese to digit"""assert type(text) == strself.result = 0.0self.result_last = 0.0if not text.strip():return self.result_lasttext = text.replace("兆", "万亿").replace("点", ".").strip(".").strip()len_text = len(text)# 判断十百千万在不在text里边,在的话就走第二个flag_pos = Truefor unit_dict_key in unit_dict_keys:if unit_dict_key in text:flag_pos = Falsebreak# 分三种情况,全数字返回原值,有中文unit_dict_keys就组合, 没有中文unit_dict_keys整合if is_total_num(text):digit_float = float(text)return digit_floatelif flag_pos:result_pos = ""for i in range(len_text):if "."!=text[i] and not text[i].isdigit():result_pos += str(digit_dict[text[i]])else:result_pos += text[i]self.result_last = float(result_pos)else:self.free_zero_and_split_three_parts(text)float_billion_hundred = self.str_to_number(self.str_billion_hundred)float_billion_one = self.str_to_number(self.str_billion_one)float_thousand_ten = self.str_to_number(self.str_thousand_ten)float_single = self.str_to_number(self.str_single)self.result = float((float_billion_hundred * 10000 + float_billion_one) * 100000000 + float_thousand_ten * 10000 + float_single)self.result_last = self.result# 重置self.str_billion = "" # 亿self.str_billion_hundred = "" # 亿万self.str_billion_one = ""self.str_thousand_ten = "" # 万self.str_single = "" # onereturn self.result_lastdef compose_decimal(self, text):"""中文小数转数字:param text:str, input of chinese, eg.["一百", "三千零七十八亿三千零十五万零三百一十二"] :return: float, result of change chinese to digit"""assert type(text) == strself.result = 0.0self.result_last = 0.0self.result_start = 0.0text = text.replace("兆", "万亿").replace("点", ".").strip()if "." in text:# 判断十百千万在不在.号后边,在的话就走compose_integer(),并且返回pos_point = text.find(".")for unit_dict_key in unit_dict_keys:if unit_dict_key in text:if pos_point < text.find(unit_dict_key):return self.compose_integer(text)# 否则就是有小数texts = text.split(".")text_start = texts[0]text_end = texts[1]# 处理整数部分if "0"==text_start or "零"==text_start:self.result_start = "0."else:self.result_start = str(int(self.compose_integer(text_start))) + "."# 处理尾部,就是后边小数部分result_pos = ""len_text = len(text_end)for i in range(len_text):if "."!=text_end[i] and not text_end[i].isdigit():result_pos += str(digit_dict[text_end[i]])else:result_pos += text_end[i]# 拼接self.result_last = float(self.result_start + result_pos) if result_pos.isdigit() else self.result_startelse:self.result_last = self.compose_integer(text)return self.result_lastclass number_to_chinese():"""codes reference: https://github.com/tyong920/a2c"""def __init__(self):self.result = ""def number_to_str_10000(self, data_str):"""一万以内的数转成大写"""res = []count = 0# 倒转str_rev = reversed(data_str) # seq -- 要转换的序列,可以是 tuple, string, list 或 range。返回一个反转的迭代器。for i in str_rev:if i is not "0":count_cos = count // 4 # 行count_col = count % 4 # 列res.append(unit_map[count_cos][count_col])res.append(num_dict[int(i)])count += 1else:count += 1if not res:res.append("零")elif res[-1] is not "零":res.append("零")# 再次倒序,这次变为正序了res.reverse()# 去掉"一十零"这样整数的“零”if res[-1] is "零" and len(res) is not 1:res.pop()return "".join(res)def number_to_str(self, data):"""分段转化"""assert type(data) == float or intdata_str = str(data)len_data = len(str(data_str))count_cos = len_data // 4 # 行count_col = len_data-count_cos*4 # 列if count_col > 0: count_cos += 1res = ""for i in range(count_cos):if i==0:data_in = data_str[-4:]elif i==count_cos-1 and count_col>0:data_in = data_str[:count_col]else:data_in = data_str[-(i+1)*4:-(i*4)]res_ = self.number_to_str_10000(data_in)if "0000"==data_in: continue # 防止零万, 零亿的情况出现res = res_ + unit_map[i][0] + res# if len(res) > 1 and res.endswith("零"): res = res[:-1]return resdef decimal_chinese(self, data):assert type(data) == float or intdata_str = str(data)if "." not in data_str:res = self.number_to_str(data_str)else:data_str_split = data_str.split(".")if len(data_str_split) is 2:res_start = self.number_to_str(data_str_split[0])res_end = "".join([num_dict[int(number)] for number in data_str_split[1]])res = res_start + random.sample(["点", "."], 1)[0] + res_endelse:res = str(data)return resdef judge_compose_decimal(data_json):"""测试小数"""ctn = chinese_to_number()for data in data_json.keys():res_dec = ctn.compose_decimal(data)if res_dec != data_json[data]:print("dec:\ttrain:" + data + "\ttrue:"+str(data_json[data])+ "\tpred:"+str(res_dec))def judge_compose_integer(data_json):"""测试整数"""ctn = chinese_to_number()for data in data_json.keys():res_dec = ctn.compose_integer(data)if res_dec != data_json[data]:print("int:\ttrain:" + data + "\ttrue:"+str(data_json[data])+ "\tpred:"+str(res_dec))if __name__=="__main__":ctn = chinese_to_number()ques = "点二八"print(ctn.compose_decimal(ques))###### 1.测试阿拉伯数字转中文 ######################################################ntc = number_to_chinese()print(ntc.decimal_chinese(230000))print(ntc.decimal_chinese(9000000000000000))for i in range(1945, 2100):# print(ntc.decimal_chinese(i))print(ntc.decimal_chinese(0.112354))print(ntc.decimal_chinese(1024.112354))
希望对你有所帮助!
常用算法实现(五)——python阿拉伯数字转中文相关推荐
- 数学建模常用算法汇总及python,MATLAB实现(二)—— 整数规划
整数规划 第3部分主要讲算法的具体实现, 如果对具体细节没有要求, 直接看1, 4就行, 直接用matlab内置的intlinprog函数或者python的cvxpy等第三方包 这里我个人更偏向于使用 ...
- 数学建模常用算法汇总及python,MATLAB实现(五) —— 拟合
拟合 比较重要的就是2.1和2.3 2.2可以浅看一下, 自己敲着试一试 就拟合部分来说, MATLAB比python强大很多, 自带cftool工具包, 并且有很多快速的函数, 个人建议使用MATL ...
- python阿拉伯数字转中文_python中将阿拉伯数字转换成中文的实现代码
#!/usr/bin/python #-*- encoding: utf-8 -*- import types class NotIntegerError(Exception): pass class ...
- Python 阿拉伯数字转换为中文大写数字
题目 python练习的一个小实验, 题目如下图: 附阿拉伯数字对应的中文大写: 思路 1. 通过定义一个字典进行阿拉伯数字与大写中文的对比储存 2. 将用户的输入首先分割为整数与小数部分分别进行处 ...
- java常用算法_五分钟记住Java常用的八种排序算法与代码实现
1.直接插入排序 经常碰到这样一类排序问题:把新的数据插入到已经排好的数据列中. 将第一个数和第二个数排序,然后构成一个有序序列 将第三个数插入进去,构成一个新的有序序列. 对第四个数.第五个数--直 ...
- 深入理解Javascript--字符串类型常用算法整理(五)
目录 一.算法在常用场景思考 1.1 算法和前后端的关联思考 1.2 前端所涉及到的算法范围侧重点思考 1.3 编程语言及框架的边界和衍变思考 1.4 足以改变世界的力量 二.字符串类型常见场景及解 ...
- 数学建模常用算法汇总及python,MATLAB实现(六) —— pandas和matlab实现插值
插值 2的拉格朗日插值用的其实比较少, 可以看一下了解一下插值的原理 主要看看3里的结论和4的实现代码 文章目录 插值 1. 定义 2.拉格朗日插值 2.1 概念 3. Rouge现象 3.1 是什么 ...
- 数学建模常用算法汇总及python,MATLAB实现(一)—— 线性规划
线性规划 文章目录 线性规划 数学原型 1. matlab求解 函数原型 2. python求解 3. 例题 matlab求解 数学原型 m i n x c ⃗ T x ⃗ s . t . { A x ...
- 阿拉伯数字与中文数字转换算法
根据<算法的乐趣>简单总结一下: 中文数字的特点 中文数字直接"数字+权位"的方式组成数字,比如阿拉伯数字100,中文表示为一百,其中"一"为数字, ...
- 【NLP】为什么中文分词比英文分词更难?有哪些常用算法?(附代码)
导读:人类文明的重要标志之一是语言文字的诞生.数千年来,几乎人类所有知识的传播都是以语言和文字作为媒介. 自然语言处理是使用计算机科学与人工智能技术分析和理解人类语言的一门学科.在人工智能的诸多范畴中 ...
最新文章
- github/python/ show me the code 25题(一)
- 隔离太无聊?每天一个数据科学项目,数据集都准备好了!
- [Android应用]《花界》V1.0 正式版隆重发布!
- autoenv的使用方法
- CodeForces - 1525D Armchairs(dp)
- 信息时代与人工智能时代的教育变革
- CPU时间分片、多线程、并发和并行
- 前端学习(2886):如何短时间内实现v-for 组件化设计方案
- Spring.Net---4、IoC/DI注入方式
- Redis-数据结构与对象-对象
- 【转】iOS多线程编程技术之NSThread、Cocoa NSOperation、GCD
- C# 反编译修改dll文件
- 计算机桌面文件为何不能剪贴,复制粘贴,详细教您电脑复制粘贴不能用了怎么解决...
- linux命令 sys,用syslinux引导多个linux系统
- gulp打包Replace Autoprefixer browsers option to Browserslist config. Use browserslis
- 微信小程序阅读器功能
- Java实现图片渲染((拖动)马赛克、黑白照、油画风格等)
- 程序员如何打造薪资15k
- 如何将文字翻译成英文?简单教程讲解
- <img>标签中alt属性和title属性的区别