| 
 
namejm 
荣誉版主
 
        batch fan
  
 
积分 5226 
发帖 1737 
注册 2006-3-10 来自 成都 
状态 离线
 | 
『楼 主』:
 [共同参与][挑战思路]中文数字阿拉伯化
 
使用 LLM 解释/回答一下
  
  头两天,无奈何 兄提出了把小写的金额转化为大写的想法: 批处理实现数字金额转大写,引来了不少高手,其中的解法让人大开眼界。
 
  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 ]  
 
    
 
  
  |  
                  
  
                    尺有所短,寸有所长,学好CMD没商量。 
考虑问题复杂化,解决问题简洁化。 |   
 | 
  2007-1-3 12:18 | 
  
 | 
 | 
 
qzwqzw 
银牌会员
 
      天的白色影子
  
 
积分 2343 
发帖 636 
注册 2004-3-6 
状态 离线
 | 
   『第 2 楼』:
 
 
使用 LLM 解释/回答一下
  
你的代码用捌仟零叁万测试有问题,具体在哪自己找找吧 
———————————————————————————————— 
另发一段完整的互转代码
 
测试中有意加了一些无效数字
 
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  
    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 ]  
 
    
 
 
 
  
 |   
 | 
  2007-1-3 23:23 | 
  
 | 
 | 
 
namejm 
荣誉版主
 
        batch fan
  
 
积分 5226 
发帖 1737 
注册 2006-3-10 来自 成都 
状态 离线
 | 
『第 3 楼』:
 
 
使用 LLM 解释/回答一下
  
  呵呵,测试不严谨,正在查错。 
 
    
 
  
  |  
                  
  
                    尺有所短,寸有所长,学好CMD没商量。 
考虑问题复杂化,解决问题简洁化。 |   
 | 
  2007-1-4 00:10 | 
  
 | 
 | 
 
qzwqzw 
银牌会员
 
      天的白色影子
  
 
积分 2343 
发帖 636 
注册 2004-3-6 
状态 离线
 | 
『第 4 楼』:
 
 
使用 LLM 解释/回答一下
  
R3仅是将RMB2Num段的结构作了调整 
 
因为算法和数据结构未变 
 
所以一些固有缺陷仅仅转变了表现方式 
 
比如嵌套的if、冗余的else set等 
 
 Last edited by qzwqzw on 2007-1-3 at 11:34 AM ] 
 
    
 
  
 |   
 | 
  2007-1-4 00:30 | 
  
 | 
 | 
 
namejm 
荣誉版主
 
        batch fan
  
 
积分 5226 
发帖 1737 
注册 2006-3-10 来自 成都 
状态 离线
 | 
『第 5 楼』:
 
 
使用 LLM 解释/回答一下
  
  经过修改,顶楼代码已经能处理形如 捌仟零叁万、捌仟零叁拾万 之类的中文数字(感谢 qzwqzw 在 2F 和 6F 指出这些问题),请各位继续测试。 
 
RE qzwqzw: 
 
  如果能把解题思路放在代码里的话,就能让别人容易理解你的算法了——开始硬着头皮看你的代码-_-||。 
 
 Last edited by namejm on 2007-1-3 at 03:10 PM ] 
 
    
 
  
  |  
                  
  
                    尺有所短,寸有所长,学好CMD没商量。 
考虑问题复杂化,解决问题简洁化。 |   
 | 
  2007-1-4 01:58 | 
  
 | 
 | 
 
qzwqzw 
银牌会员
 
      天的白色影子
  
 
积分 2343 
发帖 636 
注册 2004-3-6 
状态 离线
 | 
『第 6 楼』:
 
 
使用 LLM 解释/回答一下
  
继续用捌仟零叁拾万测试出现问题 
 
———————————————————————————————— 
 
在我的代码里 
 
:Num2RMB 段比较简单,直接按位替换数字和进位后,再针对零整问题分步替换 
 
:RMB2Num 段比较麻烦,因为算法上并不成熟,所以不想多做说明 
 
主要是对tbl2与rmb进行同步扫描 
 
两者对齐时进行数字替换并同步移位 
 
否则单独移位%tbl2%使之对齐,同时用0补空位 
 
代码本身已大体反映了算法的轮廓 
 
可能我的注释反而会加大阅读上的障碍,所以一概略去 
 
一句清晰的代码胜过十句模糊的注释 
 
    
 
  
 |   
 | 
  2007-1-4 02:32 | 
  
 | 
 | 
 
namejm 
荣誉版主
 
        batch fan
  
 
积分 5226 
发帖 1737 
注册 2006-3-10 来自 成都 
状态 离线
 | 
『第 7 楼』:
 
 
使用 LLM 解释/回答一下
  
RE qzwqzw: 
 
  一段代码确实不需要过多的注释,但是,如果能把思路一并附上的话,则效果更好,因为思路的说明信息能让人从一开始就知道这个代码的大致流程,当代码过多的时候,不至于跳转得晕头转向而忘记了每节代码的目的。 
 
  当然,提供思路说明信息只是为了能让别人更好地理解代码,是为了方便他人,不是必需的内容。 
 
    
 
  
  |  
                  
  
                    尺有所短,寸有所长,学好CMD没商量。 
考虑问题复杂化,解决问题简洁化。 |   
 | 
  2007-1-4 04:07 | 
  
 | 
 | 
 
youxi01 
高级用户
 
    
 
  
 
积分 846 
发帖 247 
注册 2006-10-27 来自 湖南==》广东 
状态 离线
 | 
  『第 8 楼』:
 
 
使用 LLM 解释/回答一下
  
来个"另类"点的吧,目前只支持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) 
  
 
    
 
 
 
  
 |   
 | 
  2007-1-4 07:45 | 
  
 | 
 | 
 
tigerpower 
中级用户
 
    大师兄
  
 
积分 377 
发帖 99 
注册 2005-8-26 
状态 离线
 | 
  『第 9 楼』:
 
 
使用 LLM 解释/回答一下
  
哈哈,偶难得写这么长的纯批处理:) 
@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 ]  
 
    
 
 
 
  
 |   
 | 
  2007-1-4 10:48 | 
  
 | 
 | 
 
tao0610 
高级用户
 
     朦胧的世界
  
 
积分 579 
发帖 218 
注册 2006-10-24 
状态 离线
 | 
『第 10 楼』:
 
 
使用 LLM 解释/回答一下
  
发一个算术法算出来的. 
要小于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 
  
 
    
 
  
  |  
                  
  
                     
认识自己,降伏自己,改变自己,才能改变别人! |   
 | 
  2007-1-5 08:28 | 
  
 | 
 | 
 
vipchenlang 
新手上路
 
 
 
  
  
积分 6 
发帖 3 
注册 2007-11-30 
状态 离线
 | 
 | 
  2007-11-30 23:51 | 
  
 | 
 | 
 
new999 
新手上路
 
 
 
  
  
积分 1 
发帖 1 
注册 2008-11-25 
状态 离线
 | 
『第 12 楼』:
 
 
使用 LLM 解释/回答一下
  
Originally posted by youxi01 at 2007-1-4 07:45: 
来个"另类"点的吧,目前只支持1亿以内的数字,欢迎测试! 
 
 
@echo off 
setlocal enabledelayedexpansion 
set str=捌仟贰佰叁拾万零柒佰零贰点零伍肆 
s ... 
  
有点问题,壹万会转成1  
 
    
 
  
 |   
 | 
  2008-12-3 18:42 | 
  
 |