标题: 【练习-034】批处理浮点计算 [打印本页]
作者: batman 时间: 2009-2-13 10:39 标题: 【练习-034】批处理浮点计算
出题目的:
掌握批处理浮点计算的方法
加分标准:
视情形加分,满分20分
解题限制:
版主级的暂请观看,但可以做解题提示
题目如下:
输入任意两个小数(小数点后最多为两位数),通过批处理输出两数的和、差、积、商
(积、商均保留两位小数)。
[ 本帖最后由 batman 于 2009-2-13 17:22 编辑 ]
作者: defanive 时间: 2009-2-13 17:43
Great,不过对分数运算更有兴趣。。。
作者: BBCC 时间: 2009-2-13 18:04
我的思路就是将小数点后面和前面分开,然后就分别计算,再加起来咯...
作者: defanive 时间: 2009-2-13 18:07
我的思路是提取掉小数点,对齐直接相加。。。
作者: BBCC 时间: 2009-2-13 18:15
也行啊...
但是如果不是两位数,而是
1.00000000000000000000000006
9.003
就麻烦了.
但在题目前提下,的确是去掉小数点这样快....
作者: defanive 时间: 2009-2-13 18:39
假若超过了CMD限制的话无论是对齐相加还是分段相加都没好结果。。。
作者: BBCC 时间: 2009-2-13 19:16
不一定这么说,有个大数算法是可以实现的...
作者: batman 时间: 2009-2-13 19:36
提示:
此题情况相当复杂,大家可要充分考虑,举个例子:当两数为-0.12 -0.08时。
作者: defanive 时间: 2009-2-13 20:47
正负倒没什么问题,主要是看小数点怎么处理。。。
作者: more 时间: 2009-2-13 20:48
做这种题目的局限性太小,而且要耗费大量的精力,个人感觉没有一个星期想完成这个题目是非常困难的,最要命的是花费了大量的精力,最终却没有一点儿实用价值,建议弄个函数,先对算式进行分析然后再进行计算,这样就是对批处理四则运算,浮点运算及大数运算方面的极大贡献了.
目前我只是分别做了加减乘除四个函数(在加法和减法函数中没有负数的运算),没有把它们集中在一个脚本里,难度太大了(主要是在对算式的分析上).
真希望哪位牛人能做出这样一个函数来...
作者: lockmove 时间: 2009-2-13 21:00
- @echo off&setlocal enabledelayedexpansion
- set /p a=1数:
- set /p b=2数:
- set a2=0
- for /f "delims=. tokens=1,2" %%i in ("%a%") do set a1=%%i&set a2=%%j
- if "%a2%"=="" goto next1
- if %a2% leq 9 goto next2
- if %a2% gtr 9 goto next3
-
- :next1
- set a2=0
- set /a a3=a1*100
- goto next4
- :next2
- set /a a3=a1*100+a2*10
- goto next4
-
- :next3
- set /a a3=a1*100+a2
- goto next4
-
- :next4
-
- for /f "delims=. tokens=1,2" %%i in ("%b%") do set b1=%%i&set b2=%%j
- if "%b2%"=="" goto next6
- if %b2% leq 9 goto next7
- if %b2% gtr 9 goto next8
- pause
-
- :next6
- set b2=0
- set /a b3=b1*100
- goto next9
- :next7
- set /a b3=b1*100+b2*10
- goto next9
-
- :next8
- set /a b3=b1*100+b2
- goto next9
-
- :next9
- set sign=2
- set /a c=a3+b3
- set "s=!c:~-%sign%!"
- echo !c:%s%=!.%s%
- pause>nul
复制代码
这是加法的
bug有不能以.6代替0.6.结果为0.6时,显示为.6
其他的减法的话c=a3-b3就可以了吧
然后乘法的话sign改成4
除法的话最好.c就是结果了.
这题差不多就这样吧.
[ 本帖最后由 lockmove 于 2009-2-13 21:30 编辑 ]
作者: defanive 时间: 2009-2-13 21:01
LS发布你做的四则函数,有用。。。
作者: BBCC 时间: 2009-2-13 21:34
在cn-dos里发过了吧,表扬一下more同学!
lockmove同学也不错,要是能改成支持任意数是多方便啊...
作者: batman 时间: 2009-2-14 01:55
先发几张程序运行的截图给大家看看,代码就先不发:
作者: 随风 时间: 2009-2-14 04:09
感觉这题不是一般的难唉,尤其是除法。。!!
赞一个先。!
作者: terse 时间: 2009-2-14 11:39
batman兄:
输入数有限制不?位数
作者: BBCC 时间: 2009-2-14 12:50
题目已经写好是两位小数啦...
作者: youxi01 时间: 2009-2-14 12:57
个人支持将含小数的分成两部分计算
以小数点为分割点,分别计算
作者: batman 时间: 2009-2-15 02:45
看来此题确是有难度,我只要公布自己的代码了(自己看着都晕得很。。。):- @echo off&setlocal enabledelayedexpansion
- set /p str=输入的两数为:
- set /a num_1=0,num_2=0,num=1,v=0
- for %%a in (%str%) do (
- set /a n+=1
- for /f "tokens=1,2 delims=." %%b in ("%%a") do (
- set "_!n!=%%b"
- if "%%c" equ "" (
- set ".!n!=00"&set /a m+=1
- if !m! equ 2 set "flag=a"
- ) else (
- set "a=%%c00"&set "a=!a:~,2!"
- set ".!n!=!a!"
- )
- )
- )
- for %%a in (+#h -#c) do (
- for /f "tokens=1,2 delims=#" %%b in ("%%a") do (
- if "%_1:~,1%" equ "-" set "k1=-"
- if "%_2:~,1%" equ "-" set "k2=-"
- set /a %%c1=_1%%b_2,%%c2=!k1!1%.1%%%100%%b!k2!1%.2%%%100
- if !%%c1! lss 0 (
- if !%%c2! leq -100 set /a %%c2+=100,%%c1-=1
- ) else (
- if !%%c1! equ 0 (
- if !%%c2! lss 0 set "%%c1=-0"&set "a=!%%c2!"&set "%%c2=!a:-=!"
- ) else (
- if !%%c2! lss 0 set /a %%c2+=100,%%c1-=1
- )
- )
- if !%%c2! geq 100 set /a %%c2-=100,%%c1+=1
- )
- )
- for %%a in (h2 c2) do (
- set "a=!%%a!"&set "a=!a:-=!"&set %%a=!a!
- if !a! lss 10 set "%%a=0!a!"
- )
- echo 其和为:%h1%.%h2%&echo 其差为:%c1%.%c2%&set /a n=0
- if defined flag set ".1="&set ".2="
- for %%a in (1 2) do (
- if "!_%%a!" equ "0" (
- set "_%%a="&set /a .%%a=1!.%%a!%%100
- ) else (
- if "!_%%a!" equ "-0" (
- set "_%%a=-"
- ) else (
- set "a=!_%%a!"&set "a=!a:-=!"
- set /a n+=1&call :lp
- )
- )
- if "!.%%a!" neq "" set "a=!.%%a!"&call :loop&set ".%%a=!a!"
- )
- set /a num1=3-num_1+num_2,m=4-v
- if defined flag set /a m=0
- if %num1% leq 0 set /a num1=2
- for /l %%a in (1,1,%num1%) do set /a num*=10
- set /a s=%_1%%.1%*num/%_2%%.2%,j=%_1%%.1%*%_2%%.2%
- if %j% lss 0 set "j=%j:-=%"&set "jk=-"
- if %s% lss 0 set "s=%s:-=%"&set "sk=-"
- if %m% neq 0 if "!j:~%m%!" equ "" set "j=0000%j%"&set "j=!j:~-%m%!"
- if %s% lss %num% set "s=%num:~1%%s%"&set "s=!s:~-%num1%!"
- if %m% neq 0 set "j=!j:~,-%m%!.!j:~-%m%,2!"
- set "s=!s:~,-%num1%!.!s:~-%num1%,2!
- for %%a in (s j) do (
- set "a=!%%a!"
- if "!a:.=!" equ "!a!" (
- set "%%a=!%%a!.00"
- ) else (
- if "!a:~-2,1!" equ "." set "%%a=!%%a!0"
- )
- if "!a:~,1!" equ "." set "%%a=0!%%a!"
- )
- echo 其积为:%jk%%j%&echo 其商为:%sk%%s%
- pause>nul&goto :eof
- :lp
- set /a num_%n%+=1&set "a=%a:~1%"
- if defined a goto lp
- goto :eof
- :loop
- if "%a:~-1%" equ "0" set "a=%a:~,-1%"&set /a v+=1&goto loop
复制代码
[ 本帖最后由 batman 于 2009-2-15 19:16 编辑 ]
作者: batman 时间: 2009-2-15 19:34
&&本人19楼的代码相当复杂,估计大家肯定会看得云里雾里,所以思来想去还
是补充代码编写思路如下,以便理解,同时期待高人出手,给出完美代码:
一、总体计算思路
大家知道本题最关键是在对小数点前后两部分数值的处理上,在楼上大家也有
过相关讨论。本人认为在加减法的处理上,应该是要将前后数值分开分别进行计
算然后再做处理(如后面小数位和满百位的处理),最后再在中间补上小数点。
而对乘法,则应是去掉小数点后前后位一起运算,最后从后向前移位补上小数点
。至于除法则是最复杂的,如结果要保留两位小数,你必须要保证除数的数位比
被除数多三位(两数均先去掉小数点),当这一条件没有得到满足时,就要给除
数后面补上足够的0,最后在结果中从后向前移位补上小数点。
二、对数值的处理
大家可以看到本人在代码中使用了海量的if语句来做判断,主要是为了处理各
种情况下的数值,大致将情况归纳如下面的12点:
1 处理原始数值无小数位的情况--从后面补上.00
2 处理原始数值小数位不满两位的情况--给小数位补上00并提取前面的两位
3 处理加减计算时小数位大于100的情况--小数位减去100,整数位加1
4 处理加减计算整数位为负小数位小于-100的情况--小数位加上100,整数位
减1
5 处理加减计算整数位为0小数位小于0的情况--整数位变为-0,小数位去掉负
号
6 处理加减计算整数位为正小数位小于0的情况--小数位加上100,整数位减1
7 处理加减计算小数位小于10的情况--在小数位前面加上0
8 处理乘除计算时两数小数位均为00的情况--将小数位置空
9 处理乘除计算时整数位为0的情况--对小数位进行取余运算
10 处理乘除计算时结果数位不够小数位的情况--在结果值前面补上足够的0并
从后向前提取小数位(如结果为负数还要先取掉负号最后再补上)
11 处理乘除计算时结果无小数位的情况--在结果后补上.00
12 处理乘除计算时结果小数位不足两位的情况--在结果后补上0
三、感言
在这次编写代码的过程中,本人深深感受到批处理在处理数值上的不足和缺陷
,这也是本人在出题时始料不及的。没想到其中要考虑的问题是方方面面错综复
杂,本人也曾几次在困难面前想要退缩,但为了给大家一个较满意的答案,还是
硬着头皮写了下来。看来批处理只适合做它适合做的事,想人为强加给它其他的
功能的确是费力不计好。
[ 本帖最后由 batman 于 2009-2-15 19:38 编辑 ]
作者: inittab 时间: 2009-5-2 22:31
练练手。基本思路是化小数为整数运算,得到结果后再恢复成小数。
不支持大数字运算。特别是乘法部分有待完善,需要考虑的成分的确太多了。可能有批漏之处- @echo off&setlocal enabledelayedexpansion
- :begin
- set /p m=输入(q退出):
- if "!m!"=="q" goto :eof
- set /p n=输入:
- for /f "tokens=1,2 delims=." %%i in ("%m%") do set m1=%%j00&if not "%%j"=="" (set mm=%%i!m1:~0,2!) else set mm=%%i00
- for /f "tokens=1,2 delims=." %%i in ("%n%") do set n1=%%j00&if not "%%j"=="" (set nn=%%i!n1:~0,2!) else set nn=%%i00
-
- if "!mm:~0,1!"=="-" (set mm=!mm:~1!&set /a num=2!mm!-1!mm!,mm=1!mm!-num&set mm=-!mm!) else set /a num=2!mm!-1!mm!,mm=1!mm!-num
- if "!nn:~0,1!"=="-" (set nn=!nn:~1!&set /a num=2!nn!-1!nn!,nn=1!nn!-num&set nn=-!nn!) else set /a num=2!nn!-1!nn!,nn=1!nn!-num
-
- set /a add=mm+nn
- call :check !add! num1
- echo 两值之和是: !num1!
-
- set /a sub=mm-nn
- call :check !sub! num2
- echo 两值之差是: !num2!
-
-
- set /a mul=mm*nn
- if !mul! lss 100 (set num3=0.00) else (
- set mul=!mul:~0,-2!
- call :check !mul! num3
- )
- echo 其积为:!num3!
-
- set /a div=100*mm/nn
- call :check !div! num4
- echo 其商为:%num4%
-
- goto begin
-
- :check
- set var=%1&set "_="
- if !var! lss 0 (set /a var=-1*var&set _=-)
- if !var! lss 10 (set var=00!var!) else if !var! lss 100 set var=0!var!
- if "!var:~-2!"=="00" (set var=!var:~0,-2!) else if "!var:~-1!"=="0" (set var=!var:~0,-2!.!var:~-2,1!) else set var=!var:~0,-2!.!var:~-2!
- set %2=!_!!var!&goto :eof
复制代码
作者: qq506657335 时间: 2010-8-29 11:20
商的取值不怎么准确。。
如23/36 你写的批处理的结果是0.63
但实际上是0.638888循环。。。
所以取值应该是0.64
作者: Hello123World 时间: 2011-7-27 16:42
回复 5# BBCC
for /f "delims=" %%a in ('%0') do (echo %%a)
是你搞错了('%0'因为"%0"),还是有什么其他的意思——我运行后批处理就不动了。
作者: zhengdalu 时间: 2011-9-22 18:22
这...我新手,请问不是批处理不支持浮点吗
作者: Batcher 时间: 2011-9-22 19:36
回复 25# zhengdalu
你自己试试就知道啦
作者: guaiwu 时间: 2011-9-22 20:20
本帖最后由 guaiwu 于 2011-9-22 20:24 编辑
- @echo off
- setlocal enabledelayedexpansion
- set /p q=请输入两个小数:
- for %%i in (%q%) do (
- set /a a+=1
- set a!a!=%%i
- )
- set /a a=%a1%+%a2%
- set /a b=%a1%-%a2%
- set /a c=%a1%*%a2%
- set /a d=%a1%/%a2%
- echo 两个小数的和为%a%
- echo 两个小数的差为%b%
- echo 两个小数相乘为%c%
- echo 两个小数相除为%d%
- pause
复制代码
作者: zhengdalu 时间: 2011-9-23 21:32
回复 26# Batcher
我试过,窗口只给显示整数位,小数没有啊。
作者: Batcher 时间: 2011-9-23 22:59
回复 28# zhengdalu
嗯,根据你试的结果,你觉得支持吗?
作者: zhengdalu 时间: 2011-9-24 15:05
我觉得不支持,可是楼主...怎么这么问啊
作者: Batcher 时间: 2011-9-24 20:12
回复 30# zhengdalu
如果你觉得不支持,为何还有25楼的疑问呢?
作者: dengyuli 时间: 2015-1-23 12:01
我发一个自己做的,是除法运算,被除数,除数都可以为小数,支持负数。
最小分度值为10^-8,可以酌情提升,不过效率会降低。
主要思路:
1、将小数化为整数,具体做法是计算被除数和除数小数部分字串的长度,若被除数的小数部分长度大于除数的小数部分的长度,则在除数的小数部分后补上0,直到除数的小数部分的长度与被除数的小数部分的长度一样,反之亦然,再去掉小数点,将被除数和除数前面的0去掉。
2、开始运算:商=被除数 整除 除数
余数=被除数 取余 除数
如果余数不等于0,商=商. 否则 完成
计数器=0
循环体
如果余数等于0,跳出循环体
循环嵌套,8次,循环变量为a
如果余数比除数小,(
余数*=10
如果循环变量大于2,商=商0
判断结束
循环嵌套结束
余数与除数的商=余数 整除 除数
余数=余数 取余 除数
商=商余数与除数的商 ::两个字符串连接
计数器加1
如果计数器大于10,跳出循环体
循环体结束- @echo off
- rem 已封装
- setlocal enabledelayedexpansion
- set ctr=0
- set "bc=%~1"
- set "c=%~2"
- set f=false
- if "!bc:~0,1!"=="-" if "!c:~0,1!"=="-" (
- set bc=!bc:-=!
- set c=!c:-=!
- set bc=!bc: =!
- set c=!c: =!
- set f=false
- ) else (
- rem nothing
- )
- if "!bc:~0,1!"=="-" if "!c:~0,1!" neq "-" (
- set bc=!bc:-=!
- set bc=!bc: =!
- set f=true
- ) else (
- rem nothing
- )
- if "!bc:~0,1!" neq "-" if "!c:~0,1!"=="-" (
- set c=!c:-=!
- set c=!c: =!
- set f=true
- ) else (
- rem nothing
- )
- set tbc=!bc!
- set tc=!c!
- set tbc=!tbc:.=!
- set tc=!tc:.=!
- set tbc=!tbc: =!
- set tc=!tc: =!
- if !"tbc!" neq "!bc!" if "!tc!" neq "!c!" (
- for /f "delims=. tokens=1-3 eol=a" %%a in ('echo !bc!') do (
- call :len %%b
- set lenbcx=!zz!
- )
- for /f "delims=. tokens=1-3 eol=a" %%a in ('echo !c!') do (
- call :len %%b
- set lencx=!zz!
- )
- ) else (
- goto :r
- )
- if !lenbcx! gtr !lencx! (
- set /a cz=lenbcx-lencx
- for /l %%a in (1,1,!cz!) do (set c=!c!0)
- set c=!c:.=!
- set c=!c: =!
- set bc=!bc:.=!
- set bc=!bc: =!
- ) else (
- if !lenbcx!==!lencx! set bc=!bc:.=! & set c=!c:.=! & set bc=!bc: =! & set c=!c: =! & goto :r
- set /a cz=lencx-lenbcx
- for /l %%a in (1,1,!cz!) do (set bc=!bc!0)
- set c=!c:.=!
- set c=!c: =!
- set bc=!bc:.=!
- set bc=!bc: =!
- )
- :r
- for /l %%a in (1,1,9) do (if "!bc:~0,1!"=="0" set bc=!bc:~1!)
- for /l %%a in (1,1,9) do (if "!c:~0,1!"=="0" set c=!c:~1!)
- set /a "s=bc/c"
- set /a "m=bc %% c"
- if !m!==0 goto :f
- set s=!s!.
- :main
- if !m!==0 goto :f
- for /l %%a in (1,1,8) do (
- if !m! lss !c! (
- set /a m=m*10
- if %%a geq 2 set s=!s!0 & set /a ctr+=1
- ) else (
- rem nothing
- )
- )
- set /a "ss=m/c"
- set /a "m=m %% !c!"
- set s=!s!!ss!
- set s=!s: =!
- set /a ctr+=1
- if !ctr! gtr 10 goto :f
- goto :main
- :f
- if !f!==false (
- echo !s!
- ) else (
- echo -!s!
- )
- goto :eof
- :len
- set "t=%1"
- set zz=0
- for /l %%a in (0,1,11) do (
- if "!t:~%%a,1!"=="" goto :eof
- set /a zz+=1
- )
- goto:eof
复制代码
作者: taofan712 时间: 2017-3-20 14:54
本帖最后由 taofan712 于 2017-3-20 15:27 编辑
回复 20# batman
最开始我也这样想,后来觉得太多意外,需要很多if。
然后我选择先把数字放大到没有小数点再计算,计算完毕再缩小倍数。
为了追求根据输入算式直接得出答案(而不是列举加减乘除4种结果),导致代码多了一半,不然代码应该在48行左右。- @echo off&setlocal enabledelayedexpansion
- title 批处理小数运算。
- set /p input=输入算式(如 2.96+0.907) :
- for /f "tokens=1,2 delims=+-*/" %%a in ("%input%") do (
- set x=%%a & set y=%%b
- call set symbol=%%input:%%a=%%
- call set symbol=%%symbol:%%b=%%
- )
- set /p precision=自定义精度(默认为3):
- if not defined precision set precision=3
- set /a xsd=1
- for /l %%a in (1 1 %precision%) do set /a xsd*=10
- echo;
- rem echo;思路:先将数字放大%xsd%倍,得到结果再缩小%xsd%倍。
- set/p=%x% %symbol% %y% 的值为:<nul
- call :largen x %precision%
- call :largen y %precision%
- if "%symbol%"=="*" set expression=x*y & set /a z=!expression!/%xsd%
- if "%symbol%"=="/" set expression=x/y & set /a z=!expression!*%xsd%
- if "%symbol%"=="+" set expression=x+y & set /a z=!expression!
- if "%symbol%"=="-" set expression=x-y & set /a z=!expression!
- call :output z
- echo;
- pause&exit /b
-
- :largen
- setlocal
- set bignum=!%~1!
- set /a _precision=%~2 + 1
- for /l %%n in (1,1,%_precision%) do set zero=!zero!0
- set multiple=1%zero%
- for /f "tokens=1,2 delims=. " %%a in ("%bignum%") do (
- set bignum_b=%%a&set bignum_e=%%b%zero%
- )
- set bignum_e=1!bignum_e:~0,%_precision%!
- set /a smallnum=bignum_b*multiple+bignum_e
- set /a smallnum+=5
- set /a smallnum-=multiple
- set smallnum=%smallnum:~0,-1%
- endlocal & set %~1=%smallnum%
- goto :eof
-
- :lessen
- setlocal
- set smallnum=!%~1!
- set _precision=%~2
- for /l %%n in (1,1,%_precision%) do set zero=!zero!0
- set multiple=1%zero%
- set /a bignum_b=smallnum/multiple
- set /a bignum_e=smallnum%%multiple
- set bignum_e=%zero%%bignum_e%
- set bignum_e=!bignum_e:~-%_precision%!
- set bignum=%bignum_b%.%bignum_e%
- endlocal & set %~1=%bignum%
- goto :eof
-
- :output
- call :lessen %~1 %precision%
- set/p= !z!<nul
- goto :eof
复制代码
作者: yhcfsr 时间: 2018-3-28 14:09
调用powershell来做数学计算吧,纯BAT光计算就很复杂了,若还要实现其他功能,真是难以想象。
时间效率不高,胜在代码简单。- set/p "input=输入表达示:
- for /f "delims=" %%a in ('powershell "%input%"') do echo %%a
- pause
复制代码
作者: LTSC1809 时间: 2023-4-9 10:43
调用powershell运算就可以了
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |