China DOS Union

-- Unite DOS · Advance DOS · Grow DOS --

Union site: www.cn-dos.net Forum site: www.cn-dos.net/forum
DOS stands for freedom, openness and progress. Let us work hard, learn from the openness and GNU spirit of FreeDOS and Linux, and together build and grow a free GNU GPL world!

中国DOS联盟论坛
The time now is 2026-07-31 21:17
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » [Joint Participation][Challenge the Approach] Arabicizing Chinese Numerals DigestI View 6,548 Replies 11
Original Poster Posted 2007-01-03 12:18 ·  中国 广东 电信
荣誉版主
★★★★
batch fan
Credits 5,226
Posts 1,737
Joined 2006-03-10 00:38
20-year member
UID 51697
From 成都
Status Offline
  A couple of days ago, brother 无奈何 proposed the idea of converting lowercase monetary amounts into uppercase: Using batch files to convert numeric amounts to uppercase, which drew in quite a few experts, and some of the solutions were really eye-opening.

  Brother qzwqzw brought up the idea of doing the reverse conversion. I thought it was very interesting, so I tried writing a bit of code. There are no error-checking statements, and I haven’t done any code simplification either. I’m posting it for everyone to test, and I also hope you can provide different solutions:

@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没商量。
考虑问题复杂化,解决问题简洁化。
Floor 2 Posted 2007-01-03 23:23 ·  中国 山西 运城 联通
银牌会员
★★★
天的白色影子
Credits 2,343
Posts 636
Joined 2004-03-06 00:00
22-year member
UID 19350
Gender Male
Status Offline
Your code has a problem when tested with 捌仟零叁万. Find exactly where it is yourself
————————————————————————————————
Posting another complete mutual-conversion code segment

I deliberately added some invalid numbers in the test

I’m very dissatisfied with the RMB2Num section

First, there is no good checking; findtsr does not support regular expressions for double-byte characters

Second, there is no good structure; defects in the design of the algorithm and data structure have led to defects in the code structure


:: 人民币大小写互转程序 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 ]
Recent Ratings for This Post ( 1 in total) Click for details
RaterScoreTime
namejm +20 2007-01-05 03:21
Floor 3 Posted 2007-01-04 00:10 ·  中国 广东 电信
荣誉版主
★★★★
batch fan
Credits 5,226
Posts 1,737
Joined 2006-03-10 00:38
20-year member
UID 51697
From 成都
Status Offline
  Hehe, the testing wasn’t rigorous. I’m checking for the error now.
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
Floor 4 Posted 2007-01-04 00:30 ·  中国 山西 运城 联通
银牌会员
★★★
天的白色影子
Credits 2,343
Posts 636
Joined 2004-03-06 00:00
22-year member
UID 19350
Gender Male
Status Offline
R3 only adjusted the structure of the RMB2Num section

Because the algorithm and data structure were not changed

So some inherent defects merely changed their form of expression

For example, nested ifs, redundant else set, and so on

[ Last edited by qzwqzw on 2007-1-3 at 11:34 AM ]
Floor 5 Posted 2007-01-04 01:58 ·  中国 广东 电信
荣誉版主
★★★★
batch fan
Credits 5,226
Posts 1,737
Joined 2006-03-10 00:38
20-year member
UID 51697
From 成都
Status Offline
  After modification, the code in the top post can already handle Chinese numerals like 捌仟零叁万 and 捌仟零叁拾万 (thanks to qzwqzw for pointing out these problems on 2F and 6F). Please keep testing it.

RE qzwqzw:

  If you could put the solution idea in the code, it would make it easier for others to understand your algorithm — I started out forcing myself to read your code -_-||.

[ Last edited by namejm on 2007-1-3 at 03:10 PM ]
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
Floor 6 Posted 2007-01-04 02:32 ·  中国 山西 运城 联通
银牌会员
★★★
天的白色影子
Credits 2,343
Posts 636
Joined 2004-03-06 00:00
22-year member
UID 19350
Gender Male
Status Offline
Continue testing with 捌仟零叁拾万 and a problem appears

————————————————————————————————

In my code

The :Num2RMB section is relatively simple: directly replace the digits and positional units by place, then do step-by-step replacements for the zero/整 issues

The :RMB2Num section is more troublesome. Since the algorithm is not mature, I don’t want to explain too much

Mainly it scans tbl2 and rmb in sync

When the two are aligned, it performs digit replacement and shifts both in sync

Otherwise, it shifts %tbl2% alone to make it align, while using 0 to fill empty positions

The code itself already roughly reflects the outline of the algorithm

Maybe my comments would instead increase the difficulty of reading, so I left them all out

One clear line of code is better than ten vague comments
Floor 7 Posted 2007-01-04 04:07 ·  中国 广东 电信
荣誉版主
★★★★
batch fan
Credits 5,226
Posts 1,737
Joined 2006-03-10 00:38
20-year member
UID 51697
From 成都
Status Offline
RE qzwqzw:

  A piece of code really does not need too many comments, but if the idea can be attached along with it, the effect is better, because the explanation of the idea lets people know the general flow of the code from the very beginning. When there is too much code, they won’t get dizzy from jumping around and forget the purpose of each section of code.

  Of course, providing an explanation of the idea is only to let others understand the code better, for others’ convenience. It is not required content.
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
Floor 8 Posted 2007-01-04 07:45 ·  中国 广东 清远 联通
高级用户
★★
Credits 846
Posts 247
Joined 2006-10-27 12:03
19-year member
UID 68504
Gender Male
From 湖南==》广东
Status Offline
Here is a more “alternative” one. At present it only supports numbers under 100 million. Testing is welcome!


@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)
Recent Ratings for This Post ( 1 in total) Click for details
RaterScoreTime
namejm +12 2007-01-05 03:21
Floor 9 Posted 2007-01-04 10:48 ·  中国 上海 闵行区 电信
中级用户
★★
大师兄
Credits 377
Posts 99
Joined 2005-08-26 07:37
20-year member
UID 41945
Status Offline
Haha, it’s rare for me to write such a long pure batch file :)
@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 ]
Recent Ratings for This Post ( 1 in total) Click for details
RaterScoreTime
namejm +16 2007-01-05 03:25
Floor 10 Posted 2007-01-05 08:28 ·  中国 北京 朝阳区 联通
高级用户
★★
朦胧的世界
Credits 579
Posts 218
Joined 2006-10-24 04:29
19-year member
UID 67972
Status Offline
Posting one calculated by an arithmetic method.
It must be less than 2147483648, and can only be an integer

@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

认识自己,降伏自己,改变自己
,才能改变别人!
Floor 11 Posted 2007-11-30 23:51 ·  中国 重庆 电信
新手上路
Credits 6
Posts 3
Joined 2007-11-30 16:40
18-year member
UID 104261
Gender Male
Status Offline
I’ve learned something again!!!!!!!!!!!!!!!!!!!!!
Floor 12 Posted 2008-12-03 18:42 ·  中国 新疆 乌鲁木齐 电信
新手上路
Credits 1
Posts 1
Joined 2008-11-25 19:07
17-year member
UID 132082
Gender Male
Status Offline
Originally posted by youxi01 at 2007-1-4 07:45:
Here is a more “alternative” one. At present it only supports numbers under 100 million. Testing is welcome!


@echo off
setlocal enabledelayedexpansion
set str=捌仟贰佰叁拾万零柒佰零贰点零伍肆
s ...


There is a bit of a problem. 壹万 gets converted to 1
Forum Jump: