|
无奈何
荣誉版主
积分 1338
发帖 356
注册 2005-7-15
状态 离线
|
『楼 主』:
[共同参与][挑战思路]批处理实现数字金额转大写
看到坛子里越来越多关于挑战批处理算法的讨论,也涌现出一批热衷于挖掘批处理潜能的兄弟,一些批处理不太适合的工作,也渐由批处理来完成,我很是高兴。
现拟一题目--数字金额转大写,这个议题在网上几乎可以找到任何流行语言的版本,唯独缺少批处理版的,这个问题当然不能指望老外来做,然后我们再借鉴 ^_^。
规则如下:
1、接收一串金额数字,转为大写,可能出现的合理格式
为 5821564130 或 5821564.130 或 5,821,564.130 等,
不会出现格式为 58.215.64.130 等小数位不明的数字或其他非金额数字字符。
2、最大位到千亿即可,最小位到分其后忽略。
3、CMD下纯批处理完成,不使用第三方工具。
4、具体转换依据见附录。
附录:
Quote: | 正确填写票据和结算凭证的基本规定
银行、单位和个人填写的各种票据和结算凭证是办理支付结算和现金收付的重要依据,直接关系到支付结算的准确、及时和安全。票据和结算凭证是银行、单位和个人凭以记载帐务的会计凭证,是记载经济业务和明确经济责任的一种书面证书。因此,填写票据和结算凭证,必须做到标准化、规范化,要要素齐全、数字正确、字迹清晰、不错漏、不潦草,防止涂改。
一、中文大写金额数字应用正楷或行书填写,如壹(壹)、贰(貳)、叁(參)、肆(肆)、伍(伍)、陆(陸)、柒、捌、玖、拾、佰、仟、万(萬)、亿、元、角、分、零、整(正)等字样。不得用一、二(两)、三、四、五、六、七、八、九、十、念、毛、另(或0)填写,不得自造简化字。如果金额数字书写中使用繁体字,如贰、陆、亿、万、圆的,也应受理。
二、中文大写金额数字到“元”为止的,在“元”之后,应写“整”(或“正”)字,在“角”之后可以不写“整”(或“正”)字。大写金额数字有“分”的,“分”后面不写“整”(或“正”)字。
三、中文大写金额数字前应标明“人民币”字样,大写金额数字有“分”的,“分”后面不写“整”(或“正”)字。
四、中文大写金额数字前应标明“人民币”字样,大写金额数字应紧接“人民币”字样填写,不得留有空白。大写金额数字前未印“人民币”字样的,应加填“人民币”三字。在票据和结算凭证大写金额栏内不得预印固定的“仟、佰、拾、万、仟、佰、拾、元、角、分”字样。
五、阿拉伯小写金额数字中有“0”时,中文大写应按照汉语语言规律、金额数字构成和防止涂改的要求进行书写。举例如下:
(一)阿拉伯数字中间有“0”时,中文大写金额要写“零”字。如¥1,409.50,应写成人民币壹仟肆佰零玖元伍角。
(二)阿位伯数字中间连续几个“0”时,中文大写金额中间可以只写一个“零”字。如¥6,007.14,应写成人民币陆仟零柒元壹角肆分。
(三)阿拉伯金额数字万位或元位是“0”,或者数字中间连续有几个“0”,万位、元位也是“0”,但千位、角位不是“0”时,中文大写金额中可以只写一个零字,也可以不写“零”字。如¥1,680.32,应写成人民币壹仟陆佰捌拾元零叁角贰分,或者写成人民币壹仟陆佰捌拾元叁角贰分;又如¥107,000.53,应写成人民币壹拾万柒仟元零伍角叁分,或者写成人民币壹拾万零柒仟元伍角叁分。
(四)阿拉伯金额数字角位是“0”,而分位不是“0”时,中文大写金额“元”后面应写“零”字。如¥16,409.02,应写成人民币壹万陆仟肆佰零玖元零贰分;又如¥325.04,应写成人民币叁佰贰拾伍元零肆分。
五、阿拉伯小写金额数字前面,均应填写人民币符号“¥”(或草写:¥)。阿拉伯小写金额数字要认真填写,不得连写分辩不清。 |
|
进制关系表:
┌─┬─┬─┬───┐
│小│简│繁│ 进制 │
├─┼─┼─┼───┤
│一│壹│壹│ 1 │
├─┼─┼─┼───┤
│二│贰│貳│ 2 │
├─┼─┼─┼───┤
│三│叁│叄│ 3 │
├─┼─┼─┼───┤
│四│肆│肆│ 4 │
├─┼─┼─┼───┤
│五│伍│伍│ 5 │
├─┼─┼─┼───┤
│六│陆│陸│ 6 │
├─┼─┼─┼───┤
│七│柒│柒│ 7 │
├─┼─┼─┼───┤
│八│捌│捌│ 8 │
├─┼─┼─┼───┤
│九│玖│玖│ 9 │
├─┼─┼─┼───┤
│十│十│拾│ 10 │
├─┼─┼─┼───┤
│百│佰│佰│ 100 │
├─┼─┼─┼───┤
│千│仟│仟│ 1000 │
├─┼─┼─┼───┤
│万│万│萬│ 10^4 │
├─┼─┼─┼───┤
│亿│亿│億│ 10^8 │
├─┼─┼─┼───┤
│兆│兆│兆│ 10^12│
└─┴─┴─┴───┘
详见:http://wiki.keyin.cn/index.php?t ... 7&variant=zh-cn
|
☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul
|
|
2007-1-1 05:58 |
|
|
youxi01
高级用户
积分 846
发帖 247
注册 2006-10-27 来自 湖南==》广东
状态 离线
|
『第
2 楼』:
写了一段到头来连自己都“看不懂”的代码:
::code by youxi01@cn-dos.net
::date 2006-1-1(Happy new year!best wishes to everyone!)
@echo off
setlocal enabledelayedexpansion
set /a a=0,b=0,c=0
::================================
::设置单位名称;
SET NAME0=仟
SET NAME1=佰
SET NAME2=拾
SET NAME3=
::================================
::=============================================
::设置数字对应的大写中文汉字
for %%i in (零 壹 贰 叁 肆 伍 陆 柒 捌 玖) do (
set BIG!a!=%%i
set /a a+=1)
::=============================================
::=======================================================================
::在以下“函数”的处理过程中,要用到"#"对数字进行对齐(都成四位),以便截取;
::这里设置凡是出现"#"的地方都设置为空。
set BIG#=
::=======================================================================
set EN=
::====================================================
::这里对输入的数字进行处理,分别取出整数部分和小数部分;
set /p EN=请输入金钱数(1000亿以内):
for /f "tokens=1,2* delims=." %%i in ("%EN%") do (
set "round=%%i"
set "dec=%%j00" 2>nul)
::=====================================================
set /a round=%round:,=%
set dec=%dec:~0,2%
:test
set /a b+=1
::=============================================
::每四位数字为一组,对原来的数据进行截取;
if %round% gtr 9999 (
set num!b!=!round:~-4!
set round=!round:~0,-4!
goto :test) else set num!b!=!round!
::==============================================
::=====================================================
::分别对1、2、3段数据进行处理;分别赋予单位:元、万、亿
::同时,分别将返回的数据传给str1,str2,str3(利用%3来控制)。
call :test1 %num1% 元 1
call :test1 %num2% 万 2
call :test1 %num3% 亿 3
::======================================================
::====================================================================
::去掉数字大写里多余的"零"。比如,1002,处理后读出来为:"壹千零贰元整"
::符合我们中国人一般的读数方法;同时将结果分别传入str1,str2,str3(%2控制)。
call :test2 %str1% 1
call :test2 %str2% 2
call :test2 %str3% 3
::=====================================================================
::==============================================================
::防止类似2,0000,1002.00形式出现错误(错误读为:2亿万1千零2元整)
if "!str2!"=="零万" set str2=零
::===============================================================
set str=%str3%%str2%%str1%
set str=%str:零元=元%
set str=%str:零万=万%
set str=%str:零亿=亿%
::防止整数部分为0;
if "%str%"=="元" set str=零元
::对小数部分数字进行处理;
if "%dec%"=="00" (set dec=整) else (
set /a dec1=!dec:~0,1!
set /a dec2=!dec:~1,1!
if !dec1! EQU 0 (set dec1=零) else call set dec1=%%BIG!dec1!%%角
if !dec2! EQU 0 (set dec2=) else call set dec2=%%BIG!dec2!%%分
set dec=!dec1!!dec2!
)
echo.
echo ========================
echo 你输入的金钱数目大写为:
echo.
echo %str:零零=零%%dec%
echo ========================
pause>nul
:test1
if not "%1"=="" (
set temp=####%1
set temp=!temp:~-4!
for /l %%i in (0 1 3) do (
set tmp%%i=!temp:~%%i,1!
if defined tmp%%i (
if !tmp%%i! GTR 0 (call set str%3=!str%3!%%BIG!tmp%%i!%%!NAME%%i!) else (
call set str%3=!str%3!%%BIG!tmp%%i!%%)))
set str%3=!str%3!%2
) else set str%3=
goto :eof
:test2
set tmp=%1
set tmp=%tmp:零零=零%
set str%2=%tmp:零零=零%
[ Last edited by youxi01 on 2007-1-1 at 11:04 PM ]
此帖被 +43 点积分 点击查看详情 评分人:【 无奈何 】 | 分数: +20 | 时间:2007-1-1 12:55 | 评分人:【 redtek 】 | 分数: +11 | 时间:2007-1-2 02:37 | 评分人:【 namejm 】 | 分数: +12 | 时间:2007-1-2 04:29 |
|
|
|
2007-1-1 12:02 |
|
|
tigerpower
中级用户
大师兄
积分 377
发帖 99
注册 2005-8-26
状态 离线
|
『第
3 楼』:
哈哈,厉害厉害!!!
去掉空行共63行,不是很长!!!
用纯粹的批处理能写出这样的程序,精彩!!!佩服!!!
美中不足有二:
1. "十"、"百"、"千"应为"拾"、"佰"、"仟",这是语文的问题,应该不算bug:)
2. 当输入是0.xx时好像有点问题。
|
|
2007-1-1 12:43 |
|
|
youxi01
高级用户
积分 846
发帖 247
注册 2006-10-27 来自 湖南==》广东
状态 离线
|
|
2007-1-1 12:50 |
|
|
无奈何
荣誉版主
积分 1338
发帖 356
注册 2005-7-15
状态 离线
|
『第
5 楼』:
RE youxi01
兄的代码转换效果非常不错。
初步测试,非常合乎规范要求,加分鼓励。
还有一点建议,帖完整功能的批处理时,推荐属上自己的名字与出处地址等,当多次转贴后,别人发现问题或想与作者交流时不因无处联系作者而苦恼,当然也会更好的保护你的劳动成果。推荐的格式为 作者@论坛 这样的形式,以上只是建议仅供参考。
RE tigerpower
零开头的数字,不为合理的金额,可以忽略,当然去除掉也不是很困难的事。
[ Last edited by 无奈何 on 2007-1-1 at 01:05 PM ]
|
☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul
|
|
2007-1-1 12:54 |
|
|
qzwqzw
银牌会员
天的白色影子
积分 2342
发帖 635
注册 2004-3-6
状态 离线
|
|
2007-1-2 00:23 |
|
|
无奈何
荣誉版主
积分 1338
发帖 356
注册 2005-7-15
状态 离线
|
『第
7 楼』:
RE qzwqzw
兄的代码也同样非常出色,并且极其简洁。
金额中含有 “,” 时会出错,“,” 也为合理的金额字符,请稍加完善一下。
兆的概念中国传统和国际单位是不同的,中国传统为一万亿。
详情可以参考下一楼给出的链接。
[ Last edited by 无奈何 on 2007-1-2 at 01:10 AM ]
|
☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul
|
|
2007-1-2 01:02 |
|
|
qzwqzw
银牌会员
天的白色影子
积分 2342
发帖 635
注册 2004-3-6
状态 离线
|
『第
8 楼』:
加了一些验证代码,很影响代码的简洁,有些郁闷
可以通过带有前缀0的数字,含,的数字,以.前缀的小数
可以禁止含有非法字符的金额
-----------------------------------------------------------------
国际单位的量级是没有兆的,只有m/K/M等
最早是谁将M译为“兆”的已经很难考证
但现在已经很流行,某些会计学教材也开始采用
------------------------------------------------------------------------
至于中国传统的计数,你可以用“亿、兆、京、垓”百度一下
--------------------------------------------------------------------------
:: 人民币金额小写转大写
:: qzwqzw@bbs.cn-dos.net
:: 2007-01-01
@echo off
setlocal EnableDelayedExpansion
set tbl1=零壹贰叁肆伍陆柒捌玖
set tbl2=分角元拾佰仟万拾佰仟亿拾佰仟
:test
cls
setlocal
set /p num=请输入小写金额(小于一万亿元,直接回车退出):
if "%num%"=="" goto :eof
set num=%num:,=%
set num=0%num%
for /f "tokens=1,2,* delims=." %%f in ("%num%") do (
set num2=%%g00
set num=%%f!num2:~0,2!
if not "%%h"=="" goto :error
)
:del_pre0
if not "%num:~0,1%"=="0" goto checknum
set num=%num:~1%
goto del_pre0
:checknum
set /a num2=num+0
if "%num%"=="%num2%" goto loop
:error
echo.
echo 输入小写金额无效!
echo.
pause
goto test
:loop
call set rmb=%%tbl1:~%num:~-1,1%,1%%%%tbl2:~%bit%,1%%%rmb%
set /a bit+=1
set num=%num:~0,-1%
if not "%num%"=="" goto loop
set rmb=%rmb:零拾=零%
set rmb=%rmb:零佰=零%
set rmb=%rmb:零仟=零%
set rmb=%rmb:零零=零%
set rmb=%rmb:零零=零%
set rmb=%rmb:零元=元零%
set rmb=%rmb:零万=万零%
set rmb=%rmb:零亿=亿零%
set rmb=%rmb:零零=零%
set rmb=%rmb:零分=零%
set rmb=%rmb:零角=零%
set rmb=%rmb:角零=角%
set rmb=%rmb:零零=整%
echo.
echo 人民币%rmb%
echo.
pause
endlocal
goto test [ Last edited by qzwqzw on 2007-1-1 at 12:36 PM ]
|
|
2007-1-2 01:28 |
|
|
无奈何
荣誉版主
积分 1338
发帖 356
注册 2005-7-15
状态 离线
|
『第
9 楼』:
RE qzwqzw
简单了解一下,传统的计数以十进制的。上面的表格称作现行通常用的好像比较合适。超大的数字也不太常用,仅当作趣闻知识吧。
|
☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul
|
|
2007-1-2 12:54 |
|
|
qzwqzw
银牌会员
天的白色影子
积分 2342
发帖 635
注册 2004-3-6
状态 离线
|
『第
10 楼』:
做了一个简单的阿拉伯数字转罗马数字的例子
考虑到规则的不统一和算法的复杂性,没有支持49->IL之类的转化
也没有支持超过4000的数字
反向转换相对困难一些
不过一旦建立了良好的数据结构,算法也就很清晰了
:: Arab2Roman 阿拉伯数字转为罗马数字
:: qzwqzw @ http://bbs.cn-dos.net
:: 2007-01-02 Revision 3
@echo off
setlocal EnableDelayedExpansion
:test
if "%~0"=="%~f0" cls
setlocal
set /p num=请输入阿拉伯数字num("0<num<4000",直接回车退出):
if "%num%"=="" goto :eof
:checknum
set /a tmp=num+0
if "%num%"=="%tmp%" if %num% lss 4000 if %num% gtr 0 goto Arab2Roman
:error
echo.
echo 无效的数字
echo.
if "%~0"=="%~f0" pause
endlocal
goto test
:Arab2Roman
set i=0
for %%v in (1000 900 500 400 100 90 50 40 10 9 5 4 1) do (
set /a i+=1
set arab!i!=%%v
)
set i=0
for %%v in (M CM D CD C XC L CL X IX V IV I) do (
set /a i+=1
set roman!i!=%%v
)
set i=1
:loop
call set tmp=%%arab%i%%%
if 1%num% lss 1%tmp% (
set /a i+=1
) else (
call set rom=%rom%%%roman%i%%%
set /a num-=tmp
)
if 1%num% gtr 10 goto loop
::Arab2Roman
echo.
echo %rom%
echo.
if "%~0"=="%~f0" pause
endlocal
goto test [ Last edited by qzwqzw on 2007-1-2 at 01:17 PM ]
|
|
2007-1-3 01:54 |
|
|
HUNRYBECKY
银牌会员
积分 1179
发帖 442
注册 2006-9-9
状态 离线
|
|
2007-1-3 02:05 |
|
|
tghksj
社区乞丐
此图片另存后死机
积分 -49
发帖 90
注册 2006-12-2
状态 离线
|
『第
12 楼』:
怎么又是 qzwqzw
我现在快成了你的FANS了.
你出一段代码,就够我看个一两天的....
老样子加上两分,拿回家看...
|
我的网络笔记本.[color=Red]非联系本人请勿访问![/color]http://w.vicp.net[img]http://zhenlove.com.cn/cndos/fileup/files/QM2.jpg[/img] |
|
2007-1-3 03:26 |
|
|
flamey
初级用户
积分 152
发帖 74
注册 2005-12-1
状态 离线
|
『第
13 楼』:
qzwqzw~~~~利害!!!!!
|
|
2007-1-3 04:51 |
|
|
qzwqzw
银牌会员
天的白色影子
积分 2342
发帖 635
注册 2004-3-6
状态 离线
|
|
2007-1-3 23:40 |
|
|
namejm
荣誉版主
batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『第
15 楼』:
呵呵,qzwqzw 厉害。建议把各种类型的转换开成专帖发表,做到专帖专用,这样有利于日后的深入讨论和论坛的检索。
|
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。 |
|
2007-1-3 23:47 |
|
|