Board logo

标题: [文本处理] 批处理把中文数字转阿拉伯数字(0~2147483647) [打印本页]

作者: aloha20200628    时间: 2022-8-9 19:47     标题: 批处理把中文数字转阿拉伯数字(0~2147483647)

本帖最后由 aloha20200628 于 2024-3-27 11:08 编辑

第一段是测试代码
第二个封装函数/子过程,是母函数 - 分段求和函数
第三个是封装函数/子过程,是子函数 - 最小段位转换函数
  1. @echo off &setlocal enabledelayedexpansion
  2. :[Loop] // 测试代码》中文数字转为阿拉伯数字(0-2147483647)
  3. set "cn="
  4. set/p cn="输入一个中文数字【零 - 二十一亿四千七百四十八万三千六百四十七】:"
  5. if not defined cn endlocal&exit/b
  6. (call :ChangeCnToAn !cn! an)
  7. echo,n=!an!
  8. goto [Loop]
  9. :: 分段求和函数》最大输出范围={ 0~2147483647 }
  10. :ChangeCnToAn // %1=中文数字符串(实值) %2=返回值变量名
  11. if "%~1"=="零" (set "%~2=0")&exit/b
  12. set "#cn#=%~1" &set "Yn=100000000"
  13. if "!#cn#:~-1!"=="亿" (
  14.     (call :ChangeCnToAn9999 !#cn#:~,-1! #n)
  15.     (set/a "%~2=!#n!*!Yn!")&exit/b
  16. )
  17. set "#cn#=!#cn#:*亿=!" &set "#cn=!#cn#:零=!"
  18. if "!#cn:万=!" neq "!#cn!" (for /f "tokens=1-2 delims=万" %%a in ("!#cn!") do (
  19.     (call :ChangeCnToAn9999 %%a nL)
  20.     set/a "#n=!nL!*10000"
  21.     if "%%b" neq "" (
  22.         (call :ChangeCnToAn9999 %%b nR)
  23.         set/a "#n+=!nR!"
  24.     )
  25. )) else (call :ChangeCnToAn9999 !#cn! #n)
  26. if "!#cn#!" neq "%~1" for /f "tokens=1-2 delims=亿" %%a in ("%~1") do (
  27.     (call :ChangeCnToAn9999 %%a nY)
  28.     (set/a "#n+=!nY!*!Yn!")
  29. )
  30. set "%~2=!#n!" &exit/b
  31. :: 最小段位转换函数》输出范围={ 0~9999 }
  32. :ChangeCnToAn9999 // %1=中文数字符串(实值) %2=返回值变量名
  33. if "%~1"=="零" set "%~2=0"&exit/b
  34. set "cn#=%~1"&set "cn#=!cn#:零=!"&set "uList=十,百,千"
  35. set/a "n#=0,一=1,二=2,三=3,四=4,五=5,六=6,七=7,八=8,九=9,十=10,百=100,千=1000"
  36. for /L %%k in (0, 2, 6) do if "!cn#:~%%k,1!" neq "" (
  37.     set "n2c=!cn#:~%%k,2!" &set "nc1=!n2c:~0,1!" &set "nc2=!n2c:~1,1!"
  38.     if "!nc2!"=="" (set/a n#+=!nc1!) else for %%c in (!nc2!) do (
  39.         if "!uList:%%c=!" neq "!uList!" (set/a n#+=!nc1!*!nc2!) else (set/a n#+=!nc1!+!nc2!)
  40.     )
  41. )
  42. set "%~2=!n#!" &exit/b
复制代码

作者: hfxiang    时间: 2022-8-10 08:58

测试好像不是俺想要的结果?
D:\bat_test>中文数字转阿拉伯数字.bat
输入一个中文数字【零 - 二十一亿四千七百四十八万三千六百四十七】:一万九千七
n=9007
作者: qixiaobin0715    时间: 2022-8-10 09:40

回复 2# hfxiang
你输入的不规范:一万九千七百
作者: hfxiang    时间: 2022-8-10 13:21

回复 3# qixiaobin0715


还是不行,测试如下:
输入一个中文数字【零 - 二十一亿四千七百四十八万三千六百四十七】:一万九千七百
n=9701

请展示一下你的规范输入后的测试结果,谢谢
作者: qixiaobin0715    时间: 2022-8-10 13:43

  1. 输入一个中文数字【零 - 二十一亿四千七百四十八万三千六百四十七】:一万九千七百
  2. n=19700
  3. 输入一个中文数字【零 - 二十一亿四千七百四十八万三千六百四十七】:一百零一
  4. n=101
  5. 输入一个中文数字【零 - 二十一亿四千七百四十八万三千六百四十七】:一亿零二十万零伍佰零一
  6. n=100200001
  7. 输入一个中文数字【零 - 二十一亿四千七百四十八万三千六百四十七】:
复制代码

作者: qixiaobin0715    时间: 2022-8-10 13:47

不知道楼主的规范写法是怎样的?最后一个未通过。
作者: hfxiang    时间: 2022-8-10 13:59

回复 5# qixiaobin0715


谢谢。从显示上看只有1个不正常。
不知为何,俺测试的好基本上都不正常。估计代码显示到网页后复制到本地时字符有出入。
作者: qixiaobin0715    时间: 2022-8-10 14:36

回复 7# hfxiang
idwma在此帖中http://bbs.bathome.net/viewthrea ... mp;page=1#pid258116的思路靠谱,分段拼接,可突破字符限制。
作者: aloha20200628    时间: 2022-8-10 15:43

中文数字的单位字符只针对》零十百千万亿,未考虑繁体字如 佰...
作者: qixiaobin0715    时间: 2022-8-10 16:15

回复 9# aloha20200628
抱歉搞错了!!!
作者: qixiaobin0715    时间: 2022-8-11 09:01

本帖最后由 qixiaobin0715 于 2022-8-11 09:15 编辑

按照idwma在其它帖子中的思路进行分段拼接,可以突破2147483647的限制,适合小于等于“九千九百九十九亿九千九百九十九万九千九百九十九”的值,再大有点复杂,未加考虑,处理一般情况就足够了:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. set str=九千九百九十九亿九千九百九十九万九千九百九十九
  4. set str=!str:零=!
  5. set str=!str:亿=亿 !
  6. set str=!str:万=万 !
  7. set _十=10
  8. for %%i in (一 二 三 四 五 六 七 八 九) do (
  9.     set /a x+=1
  10.     set /a _%%i=!x!
  11.     set y=1
  12.     for %%j in (十 百 千) do (
  13.         set /a y*=10
  14.         set /a _%%i%%j=!x!*!y!
  15.     )
  16. )
  17. for %%i in (!str!) do (
  18.     set Part=%%i
  19.     if !Part:~-1!==亿 (
  20.         set Part1=!Part:~,-1!
  21.     ) else if !Part:~-1!==万 (
  22.         set Part2=!Part:~,-1!
  23.     ) else (
  24.         set Part3=%%i
  25.     )
  26. )
  27. for /l %%i in (1,1,3) do (
  28.     if defined Part%%i (
  29.         set Part%%i=!Part%%i:千=千 !
  30.         set Part%%i=!Part%%i:百=百 !
  31.         set Part%%i=!Part%%i:十=十 !
  32.         for %%j in (!Part%%i!) do set /a m%%i+=_%%j
  33.     )
  34.     set /a m%%i+=10000
  35.     set m%%i=!m%%i:~1!
  36. )
  37. for /f "tokens=* delims=0" %%i in ("!m1!!m2!!m3!") do echo,%%i
  38. pause
复制代码
保存为ANSI编码。
代码是按照一般思路写的,考虑的还不算成熟,应当还有更简洁的方法。
作者: qixiaobin0715    时间: 2022-8-11 14:15

先以亿分为2段,再将2段以万分别分为2段,总体分为4段,最后拼接,可以扩展为16位数字。
作者: hfxiang    时间: 2024-3-27 11:42

回复 1# aloha20200628

5楼之前提出的问题还在
  1. 输入一个中文数字【零 - 二十一亿四千七百四十八万三千六百四十七】:一亿零二十万零伍佰零一
  2. n=100200001
复制代码

作者: aloha20200628    时间: 2024-3-27 12:00

回复 13# hfxiang

中文数字的输入格式应为中文小写格式》亿万千百十...而佰须改为百

作者: hfxiang    时间: 2024-3-27 12:12

回复 14# aloha20200628


    之前9楼的回复俺都已看到,但你认为的大写,其在现实应用中是存在的(是俺太不知足了,抱歉)。
作者: aloha20200628    时间: 2024-3-27 13:49

回复 15# hfxiang

中文数字大小写混合输入的问题,其实可用一个前置字典替换解决。此处不再复贴一楼全版代码了,有需求者可将如下代码行插入一楼代码第5行之后即可。
  1. for %%v in ("壹=一", "贰=二", "叁=三", "肆=四", "伍=五", "陆=六", "柒=七", "捌=八", "玖=九", "拾=十", "佰=百", "仟=千") do (set "cn=!cn:%%~v!")
复制代码

作者: hfxiang    时间: 2024-3-27 18:45

回复 16# aloha20200628
把楼主的ChangeCnToAn9999子过程修改如下,经不完全测试,好像也能实现对大写的兼容:
  1. :: 最小段位转换函数》输出范围={ 0~9999 }
  2. :ChangeCnToAn9999 // %1=中文数字符串(实值) %2=返回值变量名
  3. if "%~1"=="零" set "%~2=0"&exit/b
  4. set "cn#=%~1" &set "cn#=!cn#:零=!"&set "uList=十,拾,百,佰,千,仟"
  5. set/a "n#=0,一=1,二=2,三=3,四=4,五=5,六=6,七=7,八=8,九=9,十=10,百=100,千=1000"
  6. set/a "n#=0,壹=1,贰=2,叁=3,肆=4,伍=5,陆=6,柒=7,捌=8,玖=9,拾=10,佰=100,仟=1000"
  7. for /L %%k in (0,2,6,8,10,12) do if "!cn#:~%%k,1!" neq "" (
  8.     set "n2c=!cn#:~%%k,2!" &set "nc1=!n2c:~0,1!" &set "nc2=!n2c:~1,1!"
  9.     if "!nc2!"=="" (set/a n#+=!nc1!) else for %%c in (!nc2!) do (
  10.         if "!uList:%%c=!" neq "!uList!" (set/a n#+=!nc1!*!nc2!) else (set/a n#+=!nc1!+!nc2!)
  11.     )
  12. )
  13. set "%~2=!n#!" &exit/b
复制代码

作者: aloha20200628    时间: 2024-3-27 19:23

回复 17# hfxiang

只要能经受各种测试就好...

作者: terse    时间: 2024-3-31 19:22

本帖最后由 terse 于 2024-4-1 08:08 编辑

处理大数
头两行加上了
修正一下亿位的处理,发现bug再修正
  1. @echo off&setlocal enabledelayedexpansion
  2. set/a "零=0,一=1,二=2,三=3,四=4,五=5,六=6,七=7,八=8,九=9,十=10,百=100,千=1000,万=10000,亿=100000"
  3. set "str=八十二亿零十"
  4. set "s=!str!
  5. if "!s:~16!" neq "" (set len=16&set "s=!s:~16!") else set len=0
  6. set "s=!s!fedcba9876543210"
  7. set /a "len+=0x!s:~16,1!,result=content=num=0"
  8. set "stry="
  9. for /l %%i in (0,1,!len!) do for /f %%j in ("!str:~%%i,1!") do (
  10.      if !%%j! geq 10 (
  11.         if !%%j! gtr 1000 (
  12.             if !%%j! gtr 10000 (
  13.               set /a stry=result+content+num,result=content=0"
  14.               set stry=!stry!00000000
  15.           )else set /a "content=(content+num)*%%j,result+=content,content=0"
  16.         ) else set /a "num+=^!num,content+=num*%%j"
  17.         set "num=0"
  18.      ) else if !%%j! neq 0 set num=!%%j!
  19. )
  20. set /a "result+=content+num
  21. if defined stry (
  22.    set "s1=!stry!fedcba9876543210"
  23.    set "s2=!result!fedcba9876543210"
  24.    set /a "len=0x!s1:~16,1!-0x!s2:~16,1!"
  25.    for /f %%i in ("!len!") do echo !str! "!stry:~,%%i!!result!"
  26. ) else echo;!str! !result!
  27. pause
复制代码

作者: Ru_Evan    时间: 2024-3-31 19:57

本帖最后由 Ru_Evan 于 2024-3-31 20:01 编辑

之前写了一个,不知道放哪了。。步骤是将中文数字以亿、万分割得到三组中文数字,再分别处理三组中文数字转换成阿拉伯数字,最后三组阿拉伯数字相加而得。
作者: Ru_Evan    时间: 2024-3-31 19:58

本帖最后由 Ru_Evan 于 2024-3-31 20:02 编辑

。。。。。
作者: Five66    时间: 2024-3-31 20:52

本帖最后由 Five66 于 2024-3-31 23:58 编辑

回复 19# terse


   犯傻了 , 已编辑
作者: terse    时间: 2024-4-1 06:41

回复 22# Five66

已编辑




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2