标题: [共同参与][挑战思路]中文数字阿拉伯化
[打印本页]
作者: namejm
时间: 2007-1-3 12:18
标题: [共同参与][挑战思路]中文数字阿拉伯化
头两天,无奈何 兄提出了把小写的金额转化为大写的想法:
[共同参与][挑战思路]批处理实现数字金额转大写,引来了不少高手,其中的解法让人大开眼界。
qzwqzw 兄提出了逆向转换的想法,觉得很有意思,尝试着写了段代码,没有错误检测语句,也没有去做代码精简的工作,发出来让大家测试一下,也希望各位能提供不同的解法:
@echo off
:: Code by JM 2007-1-2~1-3 bbs.cn-dos.net CMD@XP
:: 中文形式数字转换为阿拉伯数字
:: 思路:
:: 先把所有的中文数字转化为前后带空格的阿拉伯数字(零要特殊处理),
:: 然后,把阿拉伯数字从高位到低位逐一提取出来;提取的同时,对"零"做
:: 补位及替换处理,补位的具体规则为:比较"零"前后的进位,补足相应的0,
:: 比如:某个"零"的前后进位分别为"万"和"拾",则这个"零"则替换为两个
:: 连续的0。最后,把所有的空格去掉。
setlocal enabledelayedexpansion
set str=捌仟零叁拾万零柒佰零贰点零伍肆
echo.
echo 要处理的中文数值:%str%
echo --------------------------------------------------
:: 把中文数字转化为阿拉伯数字
for /f "tokens=1* delims=点" %%i in ("%str%") do set var1=%%i&set var2=%%j
call :replace_1 %var1%
set int=%var%
if not "%var2%"=="" (
call :replace_1 %var2%
set dec=!var:零=!
)
echo.
echo 中文数字阿拉伯化的结果1:%int%.%dec%
:: 提取阿拉伯数字
call :pickup %int%
:: 检查原始数值整数部分的最后一位是不是数字,从而决定是否继续转换
if not "%int:~-1%"==" " (
set tmp=!last!
call :replace_2
)
echo.
echo 中文数字阿拉伯化的结果2:%str_%%tmp%.%dec%
if not "%dec%"=="" (
set result=%str_: =%%tmp%.%dec: =%
) else set result=%str_: =%%tmp%
echo.
echo --------------------------------------------------
echo 最终结果是:%result%
endlocal
pause>nul
goto :eof
:pickup
:: 提取阿拉伯数字,并对"零"做处理
set last=%2
if not %1 equ 0 (
set str_=!str_! %1
) else (
set str_=!str_! %zero%
set tmp=
set length=0
)
:: 对"×佰零×"之类的数要单独处理
if "%4"=="零" (
if not "%2"=="佰" (
call :replace %2 %6
) else set zero=0
)
shift
shift
if not "%1"=="" goto pickup
goto :eof
:replace
:: 对"零"做补位处理
if "%2"=="" (
set tmp=
) else (
set tmp=%2
set tmp=!tmp:~0,1!
)
set tmp=%1 %tmp%
call :replace_2
for /f "tokens=1,2" %%i in ("%tmp%") do set former=%%i&set later=%%j
:: 比较字符串 %former% 和 %later% 的长短,不能用 if %former% lss %later% 语句
set flag=!former:%later%=!
if "%flag%"=="%former%" (
set zero=%former:~1%
set flag=
goto :eof
)
:get_length
set /a length+=1
if not "%later%"=="" set later=%later:~0,-1%&goto get_length
set zero=!former:~%length%!
goto :eof
:replace_1
set var=%1
set num=1
for %%i in (壹 贰 叁 肆 伍 陆 柒 捌 玖) do (
call set var=%%var:%%i= !num! %%
set /a num+=1
)
set var=%var:零= 0 零 %
goto :eof
:replace_2
set tmp=%tmp:拾=0%
set tmp=%tmp:佰=00%
set tmp=%tmp:仟=000%
set tmp=%tmp:万=0000%
set tmp=%tmp:亿=00000000%
goto :eof
[
Last edited by namejm on 2007-1-3 at 08:18 PM ]
作者: qzwqzw
时间: 2007-1-3 23:23
你的代码用捌仟零叁万测试有问题,具体在哪自己找找吧
————————————————————————————————
另发一段完整的互转代码
测试中有意加了一些无效数字
RMB2Num段我很不满意
一者没有良好的检查,findtsr 不支持双字节字符的正则
二者没有良好的结构,算法和数据结构的设计缺陷,导致代码结构的缺陷
:: 人民币大小写互转程序 R3
:: qzwqzw http://bbs.cn-dos.net
:: 2007-01-03 11:15
@echo off
setlocal EnableDelayedExpansion
for /l %%i in (1,1,100) do (
set /a numin=!random!*50001-50000000
set numin=!numin:~0,-2!.!numin:~-2!
set in=!numin!
call :Num2RMB
set in=!out!
call :RMB2Num
echo.%%i [!numin!:!in!:!out!]
if !numin! neq !out! set /p=--- Invalid ---
set out=
)
if "%~0"=="%~f0" pause
endlocal
goto :eof
:Num2RMB
setlocal
set num=%in%
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 :eof
)
:del_pre0
if "%num:~0,1%"=="0" (
set num=%num:~1%
goto del_pre0
)
:checknum
set num=%num:,=%
set /a num2=num+0
if not "%num%"=="%num2%" goto :eof
if %num% geq 1000000000000 goto :eof
if %num% leq 0 goto :eof
set tbl1=零壹贰叁肆伍陆柒捌玖
set tbl2=分角元拾佰仟万拾佰仟亿拾佰仟
:n2r_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 n2r_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:零零=整%
endlocal & set out=%rmb%
goto :eof
::Num2RMB
:RMB2Num
setlocal
set rmb=%in%
set rmb=%rmb:零=%
set rmb=%rmb:整=%
set tbl1=零壹贰叁肆伍陆柒捌玖
set tbl2=分角元拾佰仟万拾佰仟亿拾佰仟
for /l %%i in (1,1,9) do call set rmb%%tbl1:~%%i,1%%=%%i
:r2n_loop
if "%tbl2:~0,1%"=="%rmb:~-1,1%" (
set rmb=!rmb:~0,-1!
call set tmp=%%rmb!rmb:~-1,1!%%
if not "!tmp!"=="" (
set num=!tmp!!num!
set rmb=!rmb:~0,-1!
) else (
set num=0!num!
)
) else (
set num=0!num!
)
set tbl2=%tbl2:~1%
if not "%rmb%"=="" if not "%tbl2%"=="" goto r2n_loop
set num=%num:~0,-2%.%num:~-2%
endlocal & set out=%num%
goto :eof
::RMB2Num
[
Last edited by qzwqzw on 2007-1-3 at 11:22 AM ]
作者: namejm
时间: 2007-1-4 00:10
呵呵,测试不严谨,正在查错。
作者: qzwqzw
时间: 2007-1-4 00:30
R3仅是将RMB2Num段的结构作了调整
因为算法和数据结构未变
所以一些固有缺陷仅仅转变了表现方式
比如嵌套的if、冗余的else set等
[
Last edited by qzwqzw on 2007-1-3 at 11:34 AM ]
作者: namejm
时间: 2007-1-4 01:58
经过修改,顶楼代码已经能处理形如 捌仟零叁万、捌仟零叁拾万 之类的中文数字(感谢
qzwqzw 在 2F 和 6F 指出这些问题),请各位继续测试。
RE qzwqzw:
如果能把解题思路放在代码里的话,就能让别人容易理解你的算法了——开始硬着头皮看你的代码-_-||。
[
Last edited by namejm on 2007-1-3 at 03:10 PM ]
作者: qzwqzw
时间: 2007-1-4 02:32
继续用捌仟零叁拾万测试出现问题
————————————————————————————————
在我的代码里
:Num2RMB 段比较简单,直接按位替换数字和进位后,再针对零整问题分步替换
:RMB2Num 段比较麻烦,因为算法上并不成熟,所以不想多做说明
主要是对tbl2与rmb进行同步扫描
两者对齐时进行数字替换并同步移位
否则单独移位%tbl2%使之对齐,同时用0补空位
代码本身已大体反映了算法的轮廓
可能我的注释反而会加大阅读上的障碍,所以一概略去
一句清晰的代码胜过十句模糊的注释
作者: namejm
时间: 2007-1-4 04:07
RE qzwqzw:
一段代码确实不需要过多的注释,但是,如果能把思路一并附上的话,则效果更好,因为思路的说明信息能让人从一开始就知道这个代码的大致流程,当代码过多的时候,不至于跳转得晕头转向而忘记了每节代码的目的。
当然,提供思路说明信息只是为了能让别人更好地理解代码,是为了方便他人,不是必需的内容。
作者: youxi01
时间: 2007-1-4 07:45
来个"另类"点的吧,目前只支持1亿以内的数字,欢迎测试!
@echo off
setlocal enabledelayedexpansion
set str=捌仟贰佰叁拾万零柒佰零贰点零伍肆
set /a 仟=1000,佰=100,拾=10,个=1
for %%i in (壹 贰 叁 肆 伍 陆 柒 捌 玖) do (
set/a a+=1
call set str=%%str:%%i=!a!%%)
for /f "tokens=1* delims=点" %%i in ("%str%") do set rnd=%%i&set dec=%%j
for /f "tokens=1* delims=万" %%i in ("%rnd:零=%") do (
if "%%j"=="" (
set/a num1_=0
call :test %%i 2
) else (call :test %%i 1 &call :test %%j 2))
for /f "tokens=2 delims==" %%i in ('set num1_') do set /a Res1+=%%i
for /f "tokens=2 delims==" %%i in ('set num2_') do set /a Res2+=%%i
set /a Res=%Res1%*10000+%Res2%
if "%dec%"=="" (echo !Res!) else echo !Res!.!dec:零=0!
pause>nul
:test
set tmp=%1
for /l %%i in (0 2 8) do (
set tmp_=!tmp:~%%i,2!
if not "!tmp_!"=="" (
set tmp1=!tmp_:~0,1!
set tmp2=!tmp_:~1,1!
if "!tmp2!"=="" set tmp2=个
call set /a num%2_%%i=!tmp1!*%%!tmp2!%%) else goto :eof)
作者: tigerpower
时间: 2007-1-4 10:48
哈哈,偶难得写这么长的纯批处理:)
@echo off
set USAGE=USAGE: %0 hanzi
setlocal enabledelayedexpansion
set daxie=零壹贰叁肆伍陆柒捌玖
for /l %%a in (0,1,9) do (set Arabic_poi!daxie:~%%a,1!=%%a)
for /l %%a in (0,1,9) do (set Arabic_int!daxie:~%%a,1!=+%%a)
set Arabic_poi点=.
set Arabic_int拾=*10
set Arabic_int佰=*100
set Arabic_int仟=*1000
set Arabic_int万=)*10000
set Arabic_int亿=)*100000000+(0
if "%1"=="" echo %USAGE%&&goto :eof
set input=%1。
set point=0
:loop
if not "!input!"=="" (
set chr=!input:~,1!
if "!chr!"=="点" set point=1
if "!chr!"=="万" set wan=1
if "!chr!"=="亿" set yi=1
if %point%==0 (set int=!int!!Arabic_int%chr%!) else (set poi=!poi!!Arabic_poi%chr%!)
set input=!input:~1!
goto loop)
if not defined int set int=0
if defined wan set int=(!int!
if defined yi (if not defined wan set int=(!int!^)) else set /a int=!int!&&goto end
set int_re=!int:*100000000+=!
set /a int_yi=!int:100000000+%int_re%=1!
set /a int_re=%int_re%
for /l %%i in (0,1,7) do (if "!int_re:~%%i!"=="" set int_re=0!int_re!)
set int=!int_yi!!int_re!
:end
echo %int%%poi%
[
Last edited by tigerpower on 2007-1-6 at 12:24 PM ]
作者: tao0610
时间: 2007-1-5 08:28
发一个算术法算出来的.
要小于2147483648,只能是整型
@echo off&setlocal enabledelayedexpansion
set str0=*一二三四五六七八九零壹贰叁肆伍陆柒捌玖&set b=1
color fc&mode con:cols=60 lines=15
:start
cls&echo\&echo/&echo=&echo+&echo\&echo/
setlocal
set/p str1=请输入中文数字:
if "%str1:~0,1%"=="十" set str1=%str1:*十=1十%
set str1=%str1:零=%
for %%a in (十拾 百佰 千仟) do (
set a=!a!0&&set n0=%%a
call set str1=%%str1:!n0:~0,1!=!a!+%%
call set str1=%%str1:!n0:~-1!=!a!+%%
)
:num1
if "!str1:~%nstr1%,1!"=="万" if not defined y (
set str1=(%str1%&&set/a nstr1+=1) else set str1=%str1:亿=亿(%&&set/a nstr1+=1
if "!str1:~%nstr1%,1!"=="亿" set str1=(%str1%&&set/a nstr1+=1&&set/a y+=1
if "!str1:~%nstr1%,1!"=="" goto next
set/a nstr1+=1
goto num1
:next
for %%i in (万 亿) do set/a b*=10000&&call set str1=%%str1:%%i=+0)*!b!+%%
for /l %%a in (1,1,19) do (
set n1=%%a&&call set str1=%%str1:!str0:~%%a,1!=!n1:~-1!%%)
2>nul set/a str1=%str1%+0||goto false
if %str1%==0 goto false
echo\&echo/&echo 转化为阿拉伯数字为:%str1%&goto end
:false
echo 输入有错误,请重新输入.
:end
endlocal
pause>nul&goto start
作者: vipchenlang
时间: 2007-11-30 23:51
又长见识了!!!!!!!!!!!!!!!!!!!!!
作者: new999
时间: 2008-12-3 18:42
Quote: |
Originally posted by youxi01 at 2007-1-4 07:45:
来个"另类"点的吧,目前只支持1亿以内的数字,欢迎测试!
[code]
@echo off
setlocal enabledelayedexpansion
set str=捌仟贰佰叁拾万零柒佰零贰点零伍肆
s ... |
|
有点问题,壹万会转成1