用Python递归解决阿拉伯数字转为中文财务数字格式的问题(2)--打开思路的一种方法
几天前自己写了个将阿拉伯数字转为中文财务数字的程序.用的递归,不幸的是它是树形递归.
虽然实际过程中不太可能出现金额数字大到让Python递归栈溢出,但是始终是一块心病,这玩意终究在理论上是受限制的.
我持续地零散地思考过这个问题,今天终于将其一举拿下,并且还是两个版本,一个是函数式(尾递归),一个是命令式.总算是解决一个心病了.
关键在于哪?原来的思路是从左到右转换数字,这种思路用树形递归表示并不难,但是你尝试转化为尾递归时会让你欲仙欲死..反正我是没有弄出来,还浪费了很多时间.
不知怎么的,我突然想到尝试从右到左转换,一下子就豁然开朗了.
我首先写出了个命令式版本,随后轻松翻译为尾递归版本..
这让我想起以前下象棋时,用车纵向将军后,突然发现,如果横向将军直接就赢了啊!这算是一种打开思路的方法了,即尝试从另外一个原始的位置或者方向思考如何解决问题...
是这样吗?是的,字符串从左到右和从右到左够原始吧.
unitDic=dict(zip(range(8),u'拾佰仟万拾佰仟亿'))
numDic=dict(zip('',u'零壹贰叁肆伍陆柒捌玖'))
wapDic=[(u'零拾',u'零'),(u'零佰',u'零'),(u'零仟',u'零'),
(u'零万',u'万'),(u'零亿',u'亿'),(u'亿万',u'亿'),
(u'零零',u'零'),] #函数式
def ChnNumber(s):
def wrapper(s,wd=wapDic):
def rep(s,k,v):
if k in s:
return rep(s.replace(k,v),k,v)
return s
if not wd:
return s
return wrapper(rep(s,*wd[0]),wd[1:])
def recur(s,acc='',ind=0):
if s=='':
return acc
return recur(s[:-1],numDic[s[-1]]+unitDic[ind%8]+acc,ind+1)
def end(s):
if s[-1]!='':
return numDic[s[-1]]
return ''
def result(start,end):
if end=='' and start[-1]==u'零':
return start[:-1]
return start+end
return result(wrapper(recur(s[:-1])),end(s)) #命令式
def xChnNumber(s):
def wrapper(s):
for k,v in wapDic:
while k in s:
s=s.replace(k,v)
return s
def cmd(s):
start=''
for i,char in enumerate(s[::-1]):
start=numDic[char]+unitDic[i%8]+start
return start
def end(s):
if s[-1]!='':
return numDic[s[-1]]
return ''
def result(start,end):
if end=='' and start[-1]==u'零':
return start[:-1]
return start+end
return result(wrapper(cmd(s[:-1])),end(s))
测试代码:
for i in range(18):
v1=''+''*(i+1)
v2=''+''*i+''
v3=''*(i+2)
print ('%s->%s\n%s->%s\n%s->%s'% (v1,ChnNumber(v1),v2,ChnNumber(v2),v3,ChnNumber(v3)))
print ('%s->%s\n%s->%s\n%s->%s'% (v1,xChnNumber(v1),v2,xChnNumber(v2),v3,xChnNumber(v3)))
当然Python的尾递归需要特别手段才不会在超大数字的时候出错(比如10000位数字),针对函数版,有以下办法:
class TailCaller(object) :
def __init__(self, f) :
self.f = f
def __call__(self, *args, **kwargs) :
ret = self.f(*args, **kwargs)
while type(ret) is TailCall :
ret = ret.handle()
return ret class TailCall(object) :
def __init__(self, call, *args, **kwargs) :
self.call = call
self.args = args
self.kwargs = kwargs
def handle(self) :
if type(self.call) is TailCaller :
return self.call.f(*self.args, **self.kwargs)
else :
return self.f(*self.args, **self.kwargs) def ChnNumber(s):
def wrapper(s,wd=wapDic):
@TailCaller
def rep(s,k,v):
if k in s:
return TailCall(rep,s.replace(k,v),k,v)
return s
if not wd:
return s
return wrapper(rep(s,*wd[0]),wd[1:])
@TailCaller
def recur(s,acc='',ind=0):
if s=='':
return acc
return TailCall(recur,s[:-1],numDic[s[-1]]+unitDic[ind%8]+acc,ind+1)
def end(s):
if s[-1]!='':
return numDic[s[-1]]
return ''
def result(start,end):
if end=='' and start[-1]==u'零':
return start[:-1]
return start+end
return result(wrapper(recur(s[:-1])),end(s))
用Python递归解决阿拉伯数字转为中文财务数字格式的问题(2)--打开思路的一种方法的更多相关文章
- .Net C# 阿拉伯数字转为中文金额数字
一个练习,将阿拉伯数字转为中文金额数字,针对包含整数的金额有问题 代码: public string ReturnStr(string inputNum) { ", }; string[] ...
- Java 阿拉伯数字转换为中文大写数字
Java 阿拉伯数字转换为中文大写数字 /** * <html> * <body> * <P> Copyright 1994 JsonInternational&l ...
- 解决vue项目eslint校验 Do not use 'new' for side effects 的两种方法
import Vue from 'vue' import App from './App.vue' import router from './router' new Vue({ el: '#app' ...
- PyQt(Python+Qt)学习随笔:QTableWidget中表格各列平均分配宽度的两种方法
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 在QTableWidget表格部件中,如果需要实现表格中各列要占满部件中的可用空间,同时实现各列平分 ...
- python将nan, inf转为特定的数字
最近,处理两个矩阵的点除,得到结果后,再作其他的计算,发现有些内置的函数不work:查看得到的数据,发现有很多nan和inf,导致python的基本函数运行不了,这是因为在除的过程中分母出现0的缘故. ...
- 阿拉伯数字转中文大写数字的JS
function intToChinese ( str ) { str = str+''; var len = str.length-1; var idxs = ['','十','百','千','万' ...
- python打开浏览器的三种方法
1.startfile方法 import os os.startfile("C:\Program Files (x86)\Google\Chrome\Application\chrome.e ...
- html table表格导出excel的方法 html5 table导出Excel HTML用JS导出Excel的五种方法 html中table导出Excel 前端开发 将table内容导出到excel HTML table导出到Excel中的解决办法 js实现table导出Excel,保留table样式
先上代码 <script type="text/javascript" language="javascript"> var idTmr; ...
- Oracle中中文、数字,英文混杂形式的字段进行排序的方法
http://blog.csdn.net/p451933505/article/details/9272257 对Oracle中中文.数字.英文混杂形式的字段进行排序的方法: 例如: order by ...
随机推荐
- [LeetCode] Remove 9 移除9
Start from integer 1, remove any integer that contains 9 such as 9, 19, 29... So now, you will have ...
- 重拾Python(5):数据读取
本文主要对Python如何读取数据进行总结梳理,涵盖从文本文件,尤其是excel文件(用于离线数据探索分析),以及结构化数据库(以Mysql为例)中读取数据等内容. 约定: import numpy ...
- 【实验吧】CTF_Web_天下武功唯快不破
打开链接"http://ctf5.shiyanbar.com/web/10/10.php",从页面内容未发现明显信息,查看源代码发现"please post what y ...
- Javasript设计模式之链式调用
写过jquery的可能都知道,jquery里面可以很方便的使用以下代码: // 不使用链式调用 const element = $(ele); element.addClass('red'); ele ...
- [ Java学习基础 ] Java对象的创建和销毁
类实例化可生成对象,实例方法就是对象方法,实例变量就是对象属性.一个对象的生命周期包括三个阶段:创建.使用和销毁. 创建对象 创建对象包括两个步骤:声明和实例化. 声明 声明对象与声明普通变量没有区别 ...
- 使用C# (.NET Core) 实现组合设计模式 (Composite Pattern)
本文的概念性内容来自深入浅出设计模式一书. 本文需结合上一篇文章(使用C# (.NET Core) 实现迭代器设计模式)一起看. 上一篇文章我们研究了多个菜单一起使用的问题. 需求变更 就当我们感觉我 ...
- [AHOI 2012]树屋阶梯
Description 暑假期间,小龙报名了一个模拟野外生存作战训练班来锻炼体魄,训练的第一个晚上,教官就给他们出了个难题.由于地上露营湿气重,必须选择在高处的树屋露营.小龙分配的树屋建立在一颗高度为 ...
- ●BZOJ 3270 博物馆
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3270题解: 期望DP,高斯消元 本来是定义的关于概率的dp, 但是发现这样定义有很多解释不通 ...
- UVA - 11468:Substring
随机生成一个字符可以看成在AC自动机里面向前走一个节点,那么ans就是0向前走L步并且不经过单词节点, 由概率知识可得,f[p][L]=∑f[nxt[p][i]][L-1]*g[i] 其中p表示位于p ...
- hdu 5439(找规律)
The sequence is generated by the following scheme. 1. First, write down 1, 2 on a paper. 2. The 2nd ...