如何把数字转换为汉字大写金额代码分析
出处:网络
[编程心得]又和您见面了,这次所写的是:怎样才能合理利用 VFP本身所提供的命令和函数来组织代码、编制程序,以提高运行效率。为了能说明问题,我以数字转换为大写为例,通过对
三组代码的对比来谈谈我个人对此问题的认识。
每种语言提供给我们的命令或函数,可以说最能体现这种语言的本质,而每个程序员如何运用和组织这些命令或函数,则可以直接反映这个程序员对这种语言的理解和掌握程度。现在虽然更多的是强调如何学习和掌握面向对象的编程方法,以及如何灵活运用这些对象中的事件和方法来组织代码,但我们切不可忽视对这些最基本的语言命令或函数的学习、理解和灵活掌握。
下面我们以数字转换为大写为例来加以说明:
对于如何把数字转换为汉字大写金额的编程,我在网上看到了许多种写法,代码最多的一种写法,其代码竟多达 100多行,让人看了眼花缭乱,很难理解,而代码最少的却连10行都不到,而其运行结果却是完全相同,可见理解和合理组织编程语言所提供的命令和函数是何等的重要。
考虑到版面的原因,那近百行的代码我就不具体举例了,下面的这些代码是我自行组织编写的,如有雷同,则纯属巧合:
代码一、
FUNCTION Rmbzh
1. PARA nDhsj
2. rmbxx=allt(str(nDhsj,12,2))
3. lszs=allt(str(int(nDhsj)))
4. cd0=len(lszs)
5. dws0='元拾佰千万拾佰千亿'
6. sh0='壹贰叁肆伍陆柒捌玖零'
7. rmbdx=''
8. cd1=cd0
9. for I=1 to cd0
10. lspd=right(lszs,cd1)
11. if val(lspd)=0
12. rmbdx=rmbdx+iif(cd1>4,'万元','元')
13. exit
14. endi
15. ss=int(val(subs(lszs,I,1)))
16. if ss#0
17. rem0=SUBSTRC(sh0,ss,1)+SUBSTRC(dws0,cd1,1)
18. else
19. rem0=iif(I#cd0,'零','元')
20. endi
21. rmbdx=rmbdx+rem0
22. cd1=cd1-1
23. endf
24. do while atc('零零',rmbdx)>0
25. cc=10-atc('零零',rmbdx)
26. rmbdx=strtr(rmbdx,'零零',SUBSTRC(dws0,cc,1),1,1)
27. rmbdx=strtr(rmbdx,'零零','零',1,1)
28. rmbdx=strtr(rmbdx,'零零','',1,1)
29. endd
30. lsxs=allt(str(nDhsj,12,2))
31. lsxs=right(lsxs,2)
32. if val(lsxs)#0
33. ss=int(val(subs(lsxs,1,1)))
34. rem0=SUBSTRC(sh0,ss,1)+'角'
35. rmbdx=rmbdx+rem0
36. ss=int(val(subs(lsxs,2,1)))
37. rem0=iif(ss=0,'整',SUBSTRC(sh0,ss,1)+'分')
38. rmbdx=rmbdx+rem0
39. else
40. rmbdx=rmbdx+'整'
41. endi
42. Retu rmbdx
这组代码是从纯数字的角度去考虑如何转换的,所以显得不够简洁, 比如第3行和第31行,分别把整数部分和小数部分加以分开,各自进行转换,就显的没有这个必要,但它也有可取之处,比如:
1.充分利用了系统提供的函数,尤其是SUBSTRC()这个双字节
函数。
2.它运行的结果可以达到完全口语化的汉语金额,如:
12300.00元,其运行的结果是:壹万贰千叁佰元整,完全符合支
票类填写方式。但却不符合填充类方式。
代码二、
FUNCTION Rmbzh
1. PARA nDhsj, nDW &&nDW如果等于1,表示要金额单位
2. nDzs=strt(allt(str(nDhsj,15,2)),".","") &&把小数点去掉
3. hzdx="零壹贰叁肆伍陆柒捌玖"
4. cDW="分角元拾佰仟万拾佰仟亿拾佰仟"
5. rmbdx=""
6. nCd=len(nDzs)
7. for i=1 to len(nDzs)
8. NumS=substrc(hzdx,int(val(subs(nDzs,i,1))+1),1)
9. nDWs=iif(nDW=1,substrc(cDW,nCd,1),spac(2))
10. rmbdx=rmbdx+NumS+nDwS
11. nCd=nCd-1
12. endfor
13. Retu rmbdx
这个代码就是在我网上提供下载的那个实例,可以看出它非常简洁, 编程线路清醒,第7行和第8行分别是数字转换和单位转换,不仅简单明了,而且还可根据需要选择是否需要金额单位,但也有缺点,就是不能象上例那样做到完全口语化,我之所以把它作为实例供下载,原因就在于其清晰的思路和简洁的代码组织形式。
那么这组代码还可以“精简”(其实应该叫合并)吗?答案是:当然可以。
代码三、
FUNCTION Rmbzh
1. PARA nDhsj, nDW &&nDW如果等于1,表示要金额单位
2. nDzs=strt(allt(str(nDhsj,15,2)),".","")
3. hzdx="零壹贰叁肆伍陆柒捌玖分角元拾佰仟万拾佰仟亿拾佰仟"
4. rmbdx=""
5. for i=len(nDzs) to 1 step -1
6. NumS=substrc(hzdx,2*val(subs(nDzs,len(nDzs)-i+1,1))+1,1)
7. nDws=iif(nDW=1,substrc(hzdx,i+10,1),space(2))
8. rmbdx=rmbdx+NumS+nDwS
9. endfor
10. Retu rmbdx
可以看出这组代码又比上一组少了三行代码,而其最终运行的结果是一样的,但它所带来的副作用是:代码不直观明了,不细细查看,一时难以明白,尤其是第6行和第7行中substrc()中的参数需经过多次运算方可得知,这对今后的维护带来了不便,我一般不采用这种写法。如果硬是要再合并的话,那这组代码还可以继续合并,比如可以把6-8行的代码合并为1行。
从上面的这几这几组代码我们不难看出,同一种运行目的,可以有各种不同的代码组成和表现形式,也可以体现每个程序员各自不同的编程风格,但不管如何,提高程序的运行效率是每个程序员所共同追求的。
如果您有一定的汇编知识,可以把第二组代码和第三组代码编译成可执行程序后,进行反汇编,这时您就会发现它们的汇编结果几乎是完全相同的,也就是说它们在运行时仍然把您浓缩在一行中的源代码分开,一条指令再一条指令地执行的,并不是按您源代码中的意愿,一行代码就一条指令,因而这种“合并”,对提高运行速度和效率没任何作用。既然如此,一味追求VFP源代码的“精简”
就显的毫无意义了,反而给自己带来维护的不便。所以不管如何写代码,直观清晰的编程思路和尽可能地提高运行效率才是我们所提倡的编程风格。
我谈了这么多所谓的体会,并不是说我写的代码就是高效率和完全合理的,我只是想从另一个角度来谈谈如何在学习和掌握面向对象编程的过程中,认识和重视这些最基本的知识,只有这样才不会浪费VFP为我们提供的这些非常丰富的命令和函数。
自办了这个[编程心得],我收到了许多编程爱好者的来信,希望我继续写下去,可能是由于我的水平有限,还真有些感到骑虎难下,所以每期的主题显得很凌乱,还望各位理解。如果大家觉得这个栏目对您的编程有所帮助的话,那我会继续努力的。
我期待着您的批评和建议。
我所写出的代码可能不是最合理和最精练的,只是提出一种思路或方法供大家参考,希望能对您有所帮助。
江苏 常州 老王 99.09
E-mail:cfyns@163.net
[返回] |