中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » [共同参与][挑战思路][批处理处理浮点运算]
« [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] »
作者:
标题: [共同参与][挑战思路][批处理处理浮点运算] 上一主题 | 下一主题
pengfei
银牌会员




积分 1218
发帖 485
注册 2006-7-21
来自 湖南.娄底
状态 离线
『第 46 楼』:  

qwe1234567版主43楼去小数位前置零再运算的方案很不错. 在小数进位时很好地玩了一把字符截取, 玩得漂亮. ^_^

小数整数都可以运算9位数的代码更新在4楼第一段.

加入了判断错误输入的功能. 如:
1.  如果输入的运算数中存在除阿拉伯数以外的字符, 将提示你重新输入.
2.  若小数和整数位数超过脚本运算范围, 也会让你重新输入.

该脚本为只要你能看到最终的运算结果, 应该都是正确的!

期待大家把没有考虑到的问题测试出来...

2006-10-9 05:10
查看资料  发送邮件  发短消息 网志  OICQ (573381312)  编辑帖子  回复  引用回复
pengfei
银牌会员




积分 1218
发帖 485
注册 2006-7-21
来自 湖南.娄底
状态 离线
『第 47 楼』:  

终于解决浮点运算对字符位数的限制, 理论上可以运算N位的数值范围.

算法:
1.  把输入的两个运算值, 分别以.号做为基准, 向两端补零对齐(在这之前已经去掉了无用的零), 小数和整数部分分别赋给不同变量.
2.  先运算小数部分, 将第1个数的最后一位和第2个数的最后一位做加法运算. 再将运算结果的最后一位赋给结果变量1.,如果运算结果存在两位数, 运算次低位时自动加1. 如此循环, 直到把小数的所有位数运算完成. 得到了小数部分的运算数.
2.  整数部分的运算和小数的一样. 得到结果变量2.
3.  结果变量1, 结果变量2. 将他们中间加.号就得到了准确的运算结果...

欢迎大家测试...
@echo off
if not %1*==* set num1=%1 & set num2=%2 & goto jmp
:input
cls
set num1=
set /p num1=input primary number:
set num2=
set /p num2=input number two number:
:jmp
set numx=%num1%
set numy=%num2%
echo %num1% | find "." >nul || set num1=%num1%.0
echo %num2% | find "." >nul || set num2=%num2%.0
if "%num1:~-1%"=="." set num1=%num1%0
if "%num2:~-1%"=="." set num2=%num2%0
if "%num1:~0,1%"=="." set num1=0%num1%
if "%num2:~0,1%"=="." set num2=0%num2%
set num=0
setlocal enabledelayedexpansion
for %%a in (%num1% %num2%) do (
    set /a num+=1
    for /f "tokens=1,2 delims=." %%i in ("%%a") do (
        if "!num!"=="1" (set one=%%i) else (set one_=%%i)
        if "!num!"=="1" (set two=%%j) else (set two_=%%j)
    )
)
call :omit %one%
set one=%want%
call :omit %one_%
set one_=%want%
call :raze %two%
set two=%want_%
call :raze %two_%
set two_=%want_%
if "%one%"=="" set one=0
if "%one_%"=="" set one_=0
call :go %one%
set countx=%wish%
call :go %one_%
set countx_=%wish%
if "%two%"=="" set two=0
if "%two_%"=="" set two_=0
call :go %two%
set county=%wish%
call :go %two_%
set county_=%wish%
set after=
set front=0
if %countx% lss %countx_% (
    set /a result=%countx_%-%countx%
    call :fine !result! %one%
    set one=!incept!
) else (
    set /a result=%countx%-%countx_%
    call :fine !result! %one_%
    set one_=!incept!
)
set after=0
set front=
if %county% lss %county_% (
    set /a result=%county_%-%county%
    call :fine !result! %two%
    set two=!incept!
) else (
    set /a result=%county%-%county_%
    call :fine !result! %two_%
    set two_=!incept!
)
set outcome=0
call :scale @%two% @%two_%
set decimal=%numeral:~0,-1%
call :scale @%one% @%one_%
if "%note%"=="0" (
    set integer=%numeral:~0,-1%
) else (
    set integer=1%numeral:~0,-1%
)
call :raze %decimal%
set decimal=%want_%
if "%decimal%"=="" (set dot=) else (set dot=.)
if "%numx:~0,1%"=="." set numx=0%numx%
if "%numy:~0,1%"=="." set numy=0%numy%
if "%numx:~-1%"=="." set numx=%numx:~0,-1%
if "%numy:~-1%"=="." set numy=%numy:~0,-1%
cls
echo ===============
echo 运算结果^^!
echo ===============
echo.
echo.
echo %numx%+%numy%=%integer%%dot%%decimal%
pause >nul
goto :eof

:scale
set value=%1
set value_=%2
set numeral=
:repeat
set numeral=%outcome:~-1%%numeral%
set note=0%outcome:~0,-1%
if not "%value:~-1%"=="@" (
    set xx=!value:~-1!
    set value=!value:~0,-1!
)
if not "%value_:~-1%"=="@" (
    set yy=!value_:~-1!
    set value_=!value_:~0,-1!
    call :operation !xx! !yy!
)
goto :eof
:operation
set refer=%1
set refer_=%2
set /a outcome=%refer%+%refer_%+%note%
goto repeat
:go
set remove=%1@
set wish=0
:go_
if not "!remove:~0,1!"=="@" (
    set fault=1
    for /l %%c in (0,1,9) do (
        if "!remove:~0,1!"=="%%c" (
            set /a wish+=1
            set remove=!remove:~1!
            set fault=2
            goto go_
        )
    )
    if "!fault!"=="1" goto error
    goto go_
)
goto :eof
:fine
set take=%1
set incept=%2
:fine_
if not "%take%"=="0" (
    set /a take-=1
    set incept=%front%!incept!%after%
    goto fine_
)
goto :eof
:omit
set want=%1
:omit_
if "%want:~0,1%"=="0" (
    set want=%want:~1%
    goto omit_
)
goto :eof
:raze
set want_=%1
:raze_
if "!want_:~-1!"=="0" (
    set want_=!want_:~0,-1!
    goto raze_
)
goto :eof
:error
cls
echo =====================================
echo.
echo 你的输入了非法字符^^!
echo.
echo =====================================
echo.
echo.
echo 按任意键重新输入...
pause >nul
goto input
[ Last edited by pengfei on 2006-10-11 at 09:07 ]

   此帖被 +6 点积分          点击查看详情   


附件 1: 实数加法运算脚本.rar (2006-10-11 09:11, 1.23 K, 下载附件所需积分 1 点 ,下载次数: 13)
2006-10-9 20:24
查看资料  发送邮件  发短消息 网志  OICQ (573381312)  编辑帖子  回复  引用回复
NaturalJ0
银牌会员




积分 1181
发帖 533
注册 2006-8-14
状态 离线
『第 48 楼』:  

看了下你的描述,代码还没仔细看,要是说错了别见怪。 = =b
我觉得整数部分和小数部分可以不分开。开头你已经把数位都对齐了,应该补的零也补好了。小数部分有几位也是清楚的,直接去掉小数点,当一个整数处理,处理好后再补上小数点,最后把末尾多余的零去掉。

2006-10-9 20:57
查看资料  发短消息 网志   编辑帖子  回复  引用回复
pengfei
银牌会员




积分 1218
发帖 485
注册 2006-7-21
来自 湖南.娄底
状态 离线
『第 49 楼』:  

RE:NaturlJ0

我把小数和整数分开是考虑到格式输出的问题. 如果小数部分为零就不输出0和点号.

2006-10-9 21:44
查看资料  发送邮件  发短消息 网志  OICQ (573381312)  编辑帖子  回复  引用回复
namejm
荣誉版主

batch fan


积分 5226
发帖 1737
注册 2006-3-10
来自 成都
状态 离线
『第 50 楼』:  

  我也来一段代码,按位做加法操作的,理论上可以对N位的数值进行处理。稍显遗憾的是,对输入的检测不甚严格。
@echo off
:: 分别把两个数的整数和小数部分提取出来
:: 整数部分在高位用0补齐,小数部分在低位用0填充,使得两个数的数位各自对齐
:: 从小数的最低位开始,按位计算两个数的和,超过9就向次高位进1,只到整数的最高位为止
:: 例如:要计算 4567.5+5.6789,则处理后的数字为4567.5000+0005.6789,然后按位做加法操作

:main
cls
set num1=
set num2=
set /p num1=请输入第一个数:
call :input_check "%num1%" num1
set /p num2=请输入第二个数:
call :input_check "%num2%" num2

setlocal enabledelayedexpansion
for /f "tokens=1-4 delims=." %%i in ("%num1%.%num2%") do (
    set int1=%%i
    set int2=%%k
    set dec1=%%j
    set dec2=%%l
    call :get_length int1 %%i
    call :get_length int2 %%k
    call :get_length dec1 %%j
    call :get_length dec2 %%l
    call :add_zero
    call :sum
)
pause
goto :eof

:input_check
rem =========== 检测输入是否正确 ===========
echo %1|findstr "\.">nul||set %~2=%~1.0
for /f "tokens=1* delims=." %%i in (%1) do (
    echo %%i%%j|findstr "^[0-9]*$">nul || goto main
)
goto :eof   

:get_length
rem =========== 计算各部分数字的长度 ===========
set count=0
:intercept
set /a count+=1
for /f %%i in ("%2") do (
    set var=%%i
    if not "!var:~%count%,1!"=="" goto intercept
    set %1_length=!count!
)
goto :eof

:add_zero
rem =========== 分别在整数部分和小数部分添加0字符串 ===========
:: 在数位不够的整数部分添0补齐
set /a int_length_diff=%int1_length%-%int2_length%
set int_length_diff=%int_length_diff:-=%
call :creat_zero int_zero %int_length_diff%
if %int1_length% gtr %int2_length% (
    set int2=%int_zero%%int2%
    set int_length_max=%int1_length%
    ) else (
    set int1=%int_zero%%int1%
    set int_length_max=%int2_length%
)
:: 在数位不够的小数部分添0补齐
set /a dec_length_diff=%dec1_length%-%dec2_length%
set dec_length_diff=%dec_length_diff:-=%
call :creat_zero dec_zero %dec_length_diff%
if %dec1_length% gtr %dec2_length% (
    set dec2=%dec2%%dec_zero%
    set dec_length_max=%dec1_length%
    ) else (
    set dec1=%dec1%%dec_zero%
    set dec_length_max=%dec2_length%
)
goto :eof

:creat_zero
rem =========== 根据数字字符串长度的差异,生成相应长度的0字符串 ===========
set zero=
for /l %%i in (1,1,%2) do set zero=!zero!0
set %1=%zero%
goto :eof

:sum
rem =========== 对小数部分和整数部分分别求和 ===========
:: 计算小数部分
set dec_sum=
set tmp_sum=
set switch=0
for /l %%i in (1,1,%dec_length_max%) do (
    set dec1_char=!dec1:~-%%i,1!
    set dec2_char=!dec2:~-%%i,1!
    set /a tmp_sum=!dec1_char!+!dec2_char!+!switch!
    if !tmp_sum! gtr 9 (
        set /a tmp_sum=!tmp_sum!-10
        set switch=1
        ) else (
        set switch=0
    )
    set dec_sum=!tmp_sum!!dec_sum!
)

:: 计算整数部分
set int_sum=
set tmp_sum=
for /l %%i in (1,1,%int_length_max%) do (
    set int1_char=!int1:~-%%i,1!
    set int2_char=!int2:~-%%i,1!
    set /a tmp_sum=!int1_char!+!int2_char!+!switch!
    if !tmp_sum! gtr 9 (
        set /a tmp_sum=!tmp_sum!-10
        set switch=1
        ) else (
        set switch=0
    )
    set int_sum=!tmp_sum!!int_sum!
)
if %switch% equ 1 (
    echo  %num1%+%num2%=1%int_sum%.%dec_sum%
    ) else (
    echo  %num1%+%num2%=%int_sum%.%dec_sum%
)
goto :eof
[ Last edited by namejm on 2006-10-10 at 09:32 ]

   此帖被 +6 点积分          点击查看详情   




尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
2006-10-10 09:12
查看资料  发短消息 网志   编辑帖子  回复  引用回复
pengfei
银牌会员




积分 1218
发帖 485
注册 2006-7-21
来自 湖南.娄底
状态 离线
『第 51 楼』:  

namejm兄也得不错吗. ^_^

47楼代码修正了最后进位时的毛病, 多谢namejm兄提醒.

欢迎大家测试...

2006-10-10 09:48
查看资料  发送邮件  发短消息 网志  OICQ (573381312)  编辑帖子  回复  引用回复
redtek
金牌会员





积分 2902
发帖 1147
注册 2006-9-21
状态 离线
『第 52 楼』:  

建议将代码传入国际著名的DOS批处理交流网站(我不知道是哪个站点),
代码上标注上 www.cn-dos.net 以及 China 中国字样~:)

将来把创新、改进、实用的东东同时也放到全世界著名的批处理交流网站上(英文站点),让这些智慧的创造烙上中国的印章~:)

2006-10-10 20:43
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
pengfei
银牌会员




积分 1218
发帖 485
注册 2006-7-21
来自 湖南.娄底
状态 离线
『第 53 楼』:  

其实批处理和其他高级语言一样, 算法是灵魂, 创新是动力. 而结构化程序设计的思想是我们必须坚持的理念.

三种基本结构(顺序结构, 选择结构, 循环结构)是可以解决任何复杂问题的.

当你更深地认识了这种结构化的设计思路, 写代码也就非常容易了.

2006-10-10 22:50
查看资料  发送邮件  发短消息 网志  OICQ (573381312)  编辑帖子  回复  引用回复
electronixtar
铂金会员





积分 7493
发帖 2672
注册 2005-9-2
状态 离线
『第 54 楼』:  

五体投地~~




C:\>BLOG http://initiative.yo2.cn/
C:\>hh.exe ntcmds.chm::/ntcmds.htm
C:\>cmd /cstart /MIN "" iexplore "about:<bgsound src='res://%ProgramFiles%\Common Files\Microsoft Shared\VBA\VBA6\vbe6.dll/10/5432'>"
2006-10-11 01:21
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
namejm
荣誉版主

batch fan


积分 5226
发帖 1737
注册 2006-3-10
来自 成都
状态 离线
『第 55 楼』:  

  到目前为止,各位的代码都只能处理非负的浮点数,下一步该考虑一下怎么处理纯负数、正负数混合的情况,以使得代码能真正处理所有的浮点数。



尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
2006-10-11 01:26
查看资料  发短消息 网志   编辑帖子  回复  引用回复
pengfei
银牌会员




积分 1218
发帖 485
注册 2006-7-21
来自 湖南.娄底
状态 离线
『第 56 楼』:  

经过测试, 我47楼的代码和namejm版主的代码已经没有任何问题.

这个问题得到完美的解决, 不但能够处理浮点运算, 还解决了批处理运算位数的限制(发现很多计算器都有位数限制,  windows自带的计算器只能运算31位. 看来我们的脚本在这个方面可以发挥他的特长了, 哈哈~~~!)

正想把这个无限制加减法运算的代码合并, 代码正在编写ing...  将放到我那个实数运算脚本的帖子中去!

2006-10-11 01:33
查看资料  发送邮件  发短消息 网志  OICQ (573381312)  编辑帖子  回复  引用回复
vkill
金牌会员





积分 4103
发帖 1744
注册 2006-1-20
来自 甘肃.临泽
状态 离线
『第 57 楼』:  

佩服,佩服~~

2006-10-11 02:09
查看资料  发送邮件  访问主页  发短消息 网志   编辑帖子  回复  引用回复
不得不爱
超级版主

我爱DOS


积分 5310
发帖 2044
注册 2005-9-26
来自 四川南充
状态 离线
『第 58 楼』:  

终于解决浮点运算对字符位数的限制, 理论上可以运算N位的数值范围.
分别把两个数的整数和小数部分提取出来
小数部分在低位用0填充,使得两个数的数位各自对齐
从小数的最低位开始,按每位计算1次两个数的和,超过9就向次高位进1,直到整数的最高位为止
(47楼计算带2个小数点的小数出现错误,
32165.464.1654 +1321.654.31654 =33487.1118
50楼计算首位是小数点也出现错误,
请输入第一个数:.31654
请输入第二个数:1.31654
找不到操作数。
命令语法不正确。)
在本代码了都没有哪两个问题。47楼和50楼的代码还需要改进。
@echo off
setlocal enabledelayedexpansion
if not %1*==* (set num1=%1&if not %2*==* (set num2=%2&goto jmp) ELSE goto err)
ECHO 1
:input
set/p num1=请输入第一个小数:
set/p num2=请输入第二个小数:
:jmp
if %num1%*==* goto err
if %num2%*==* goto err
set err=0
if %num1:~0,1%==. set num1=0%num1%
call :qc "%num1%" num1
if %num2:~0,1%==. set num2=0%num2%
call :qc "%num2%" num2
if %err%==1 goto err
for /f "tokens=1* delims=." %%a in ("%num1%") do (set o1=%%a
set t1=%%b)
for /f "tokens=1* delims=." %%a in ("%num2%") do (set o2=%%a
set t2=%%b)
call :qs0 %o1%
set o1=%sw%
call :qs0 %o2%
set o2=%sw%
call :qw0 %t1%
set t1=%sw%
call :qw0 %t2%
set t2=%sw%
call :js %t1%
set s1=%sw%
call :js %t2%
set s2=%sw%
If %s1% Geq %s2% (set/a s3=%s1%-%s2%
call :j0 !s3! %t2%
set tmp1=%o1%%t1%
set tmp2=%o2%!sw!
) ELSE (set/a s3=%s2%-%s1%
call :j0 !s3! %t1%
set tmp1=%o1%!sw!
set tmp2=%o2%%t2%
set s1=%s2%)
set jg1=0
set jg=
ECHO %tmp1% %tmp2%
:js2
set/a jg0=%tmp1:~-1%+%tmp2:~-1%+%jg1%
set jg1=0%jg0:~0,-1%
set jg=%jg0:~-1%%jg%
set tmp1=%tmp1:~0,-1%
set tmp2=%tmp2:~0,-1%
if %tmp1%*==* (if %tmp2%*==* (if %jg1%==01 (set jg=1%jg%&goto xs) ELSE goto xs) ELSE set tmp1=0&goto js2)
if %tmp2%*==* (if %jg1%==01 (set tmp2=0&goto js2) ELSE (set jg=%tmp1%%jg%&goto xs))
goto js2
:xs
call :qw0 !jg:~-%s1%!
set jg=!jg:~0,-%s1%!.%sw%
if %jg:~-1%==0 set jg=%jg:~0,-2%
:cls
echo 计算结果是:
if not %t1%==0 set o1=%o1%.%t1%
if not %t2%==0 set o2=%o2%.%t2%
echo %o1%+%o2%=%jg%
pause
goto :eof

:qs0
set sw=%1
:qs1
if %sw%==0 goto :eof
if %sw:~0,1%==0 set sw=!sw:~1!&goto qs1
goto :eof
:qw0
set sw=%1
:qw1
if %sw%==0 goto :eof
if %sw:~-1%==0 set sw=!sw:~0,-1!&goto qw1
goto :eof
:js
set sw=0
set sw1=%1
if %sw1%==0 set sw=1&goto :eof
:js1
if not %sw1%*==* set sw1=%sw1:~1%&set/a sw+=1&goto js1
goto :eof
:qc
echo %1|findstr "\.">nul||set %~2=%~1.0
for /f "tokens=1* delims=." %%i in (%1) do echo %%i%%j|findstr "^[0-9]*$">nul||set err=1
goto :eof
:j0
set sw1=%1
set sw=%2
if %sw1%==0 goto :eof
for /l %%c in (1,1,%sw1%) do set sw=!sw!0
goto :eof
:err
echo 你输入了非法字符^!
echo 请重新输入...
goto input
[ Last edited by qwe1234567 on 2006-10-11 at 09:33 ]

   此帖被 +4 点积分        点击查看详情   
评分人:【 分数: +4  时间:2006-10-14 10:13


附件 1: 实数计算脚本.rar (2006-10-11 09:33, 834 bytes, 下载附件所需积分 1 点 ,下载次数: 9)


我的网络U盘 我的网络第2个U盘
论坛软件下载链接
灵雨飘零论坛  
论坛新手必读,所有人的基本行为准则
刷QQ空间人气、留言的小软件
2006-10-11 02:46
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
不得不爱
超级版主

我爱DOS


积分 5310
发帖 2044
注册 2005-9-26
来自 四川南充
状态 离线
『第 59 楼』:  



  Quote:
Originally posted by pengfei at 2006-10-11 01:33:
经过测试, 我47楼的代码和namejm版主的代码已经没有任何问题.

这个问题得到完美的解决, 不但能够处理浮点运算, 还解决了批处理运算位数的限制(发砮..

两位的代码都有点问题!看下我的!



我的网络U盘 我的网络第2个U盘
论坛软件下载链接
灵雨飘零论坛  
论坛新手必读,所有人的基本行为准则
刷QQ空间人气、留言的小软件
2006-10-11 02:47
查看资料  发送邮件  发短消息 网志   编辑帖子  回复  引用回复
vkill
金牌会员





积分 4103
发帖 1744
注册 2006-1-20
来自 甘肃.临泽
状态 离线
『第 60 楼』:  



  Quote:
Originally posted by qwe1234567 at 2006-10-11 02:46:
终于解决浮点运算对字符位数的限制, 理论上可以运算N位的数值范围.
分别把两个数的整数和小数部分提取出来
小数部分在低位用0填充,使得两个数 ...

计算结果是:
0.9999999999999999999999999999999999999999999999999999999999999+0.77777777777777
7=177.7777769777777769999999999999999999999999999999999999999999999
请按任意键继续. . .
???

2006-10-11 02:52
查看资料  发送邮件  访问主页  发短消息 网志   编辑帖子  回复  引用回复
« [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] »
请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: