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-06-20 14:35
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » [Joint Participation] [Challenge Ideas] [Batch Processing Floating-Point Operations] DigestI View 41,151 Replies 136
Floor 46 Posted 2006-10-09 05:10 ·  中国 湖南 娄底 新化县 电信
银牌会员
★★★
Credits 1,218
Posts 485
Joined 2006-07-21 21:24
19-year member
UID 58987
From 湖南.娄底
Status Offline
Moderator qwe1234567’s scheme on the 43rd floor of removing leading zeros in the decimal part before calculating is very good. When carrying in the decimal part, it plays with character interception very nicely. Well played. ^_^

The code where both decimals and integers can calculate 9 digits has been updated in the first section on the 4th floor.

Added the function of judging erroneous input. For example:
1. If the entered operand contains characters other than Arabic numerals, it will prompt you to enter again.
2. If the decimal and integer digit counts exceed the script calculation range, it will also ask you to enter again.

With this script, as long as you can see the final calculation result, it should be correct!

Looking forward to everyone testing out problems not yet considered...
Floor 47 Posted 2006-10-09 20:24 ·  中国 湖南 娄底 新化县 电信
银牌会员
★★★
Credits 1,218
Posts 485
Joined 2006-07-21 21:24
19-year member
UID 58987
From 湖南.娄底
Status Offline
Finally solved the limitation of floating-point calculation on the number of character digits. In theory it can calculate a value range of N digits.

Algorithm:
1. Take the two input calculation values, use the . sign as the reference, and pad zeros toward both ends to align them (before this, useless zeros have already been removed). Assign the decimal and integer parts to different variables respectively.
2. First calculate the decimal part: add the last digit of the first number and the last digit of the second number. Then assign the last digit of the calculation result to result variable 1. If the calculation result has two digits, automatically add 1 when calculating the next higher digit. Loop like this until all digits of the decimal part have been calculated. This obtains the operand of the decimal part.
2. Calculation of the integer part is the same as that of the decimal part. Obtain result variable 2.
3. Result variable 1, result variable 2. Add a . sign between them and you get the accurate calculation result...

Everyone is welcome to test...


@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 Calculation result^^!
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 You entered illegal characters^^!
echo.
echo =====================================
echo.
echo.
echo Press any key to enter again...
pause >nul
goto input


[ Last edited by pengfei on 2006-10-11 at 09:07 ]
Attachments
实数加法运算脚本.rar (1.23 KiB, Credits to download 1 pts, Downloads: 13)
Floor 48 Posted 2006-10-09 20:57 ·  中国 江苏 苏州 电信
银牌会员
★★★
Credits 1,181
Posts 533
Joined 2006-08-14 12:54
19-year member
UID 60484
Status Offline
I looked at your description; I haven’t looked carefully at the code yet, so don’t take offense if I’m wrong. = =b
I think the integer part and decimal part do not need to be separated. At the beginning you have already aligned all the digit positions, and the zeros that should be padded have also been padded. The number of decimal digits is also clear. Just remove the decimal point directly, handle it as an integer, then add the decimal point back after processing, and finally remove the extra zeros at the end.
Floor 49 Posted 2006-10-09 21:44 ·  中国 湖南 娄底 新化县 电信
银牌会员
★★★
Credits 1,218
Posts 485
Joined 2006-07-21 21:24
19-year member
UID 58987
From 湖南.娄底
Status Offline
RE:NaturlJ0

I separated the decimal and integer parts in consideration of the formatted output problem. If the decimal part is zero, then do not output 0 and the dot.
Floor 50 Posted 2006-10-10 09:12 ·  中国 广东 佛山 广东睿江科技有限公司
荣誉版主
★★★★
batch fan
Credits 5,226
Posts 1,737
Joined 2006-03-10 00:38
20-year member
UID 51697
From 成都
Status Offline
  I’ll also post a section of code. It does addition digit by digit; in theory it can process N-digit values. A slight pity is that the input checking is not very strict.

@echo off
:: Separately extract the integer and decimal parts of the two numbers
:: Pad the integer parts with 0 on the high side, and fill the decimal parts with 0 on the low side, so that the digit positions of the two numbers are aligned respectively
:: Starting from the lowest digit of the decimal, calculate the sum of the two numbers digit by digit; if it exceeds 9, carry 1 to the next higher digit, until the highest digit of the integer
:: For example: to calculate 4567.5+5.6789, the processed numbers are 4567.5000+0005.6789, then do addition digit by digit

:main
cls
set num1=
set num2=
set /p num1=Please enter the first number:
call :input_check "%num1%" num1
set /p num2=Please enter the second number:
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 =========== Check whether input is correct ===========
echo %1|findstr "\.">nul||set %~2=%~1.0
for /f "tokens=1* delims=." %%i in (%1) do (
echo %%i%%j|findstr "^*$">nul || goto main
)
goto :eof

:get_length
rem =========== Calculate the length of the digits in each part ===========
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 =========== Add 0 strings to the integer part and decimal part respectively ===========
:: Add 0 to pad the integer part with insufficient digit positions
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%
)
:: Add 0 to pad the decimal part with insufficient digit positions
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 =========== According to the difference in numeric string lengths, generate a 0 string of the corresponding length ===========
set zero=
for /l %%i in (1,1,%2) do set zero=!zero!0
set %1=%zero%
goto :eof

:sum
rem =========== Sum the decimal part and integer part separately ===========
:: Calculate the decimal part
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!
)

:: Calculate the integer part
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 ]
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
Floor 51 Posted 2006-10-10 09:48 ·  中国 湖南 娄底 新化县 电信
银牌会员
★★★
Credits 1,218
Posts 485
Joined 2006-07-21 21:24
19-year member
UID 58987
From 湖南.娄底
Status Offline
Brother namejm’s is not bad either. ^_^

The code on the 47th floor has corrected the problem with the final carry. Many thanks to brother namejm for the reminder.

Everyone is welcome to test...
Floor 52 Posted 2006-10-10 20:43 ·  中国 北京 东城区 联通
金牌会员
★★★★
Credits 2,902
Posts 1,147
Joined 2006-09-21 12:00
19-year member
UID 63324
Gender Male
Status Offline
I suggest submitting the code to some internationally famous DOS batch discussion website (I don't know which site it is),
and marking the code with www.cn-dos.net as well as the words China and 中国~:)

In the future, innovative, improved, and practical stuff should also be posted on world-famous batch discussion websites (English sites), so that these creations of wisdom carry the imprint of China~:)
Floor 53 Posted 2006-10-10 22:50 ·  中国 湖南 娄底 新化县 电信
银牌会员
★★★
Credits 1,218
Posts 485
Joined 2006-07-21 21:24
19-year member
UID 58987
From 湖南.娄底
Status Offline
Actually batch files are the same as other high-level languages: algorithms are the soul, and innovation is the driving force. And the idea of structured programming is a principle we must stick to.

The three basic structures (sequence structure, selection structure, loop structure) can solve any complex problem.

When you understand this structured design approach more deeply, writing code becomes very easy.
Floor 54 Posted 2006-10-11 01:21 ·  中国 四川 成都 教育网
铂金会员
★★★★
Credits 7,493
Posts 2,672
Joined 2005-09-02 00:00
20-year member
UID 42173
Gender Male
Status Offline
Totally in awe~~

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'>"
Floor 55 Posted 2006-10-11 01:26 ·  中国 广东 佛山 广东睿江科技有限公司
荣誉版主
★★★★
batch fan
Credits 5,226
Posts 1,737
Joined 2006-03-10 00:38
20-year member
UID 51697
From 成都
Status Offline
  Up to now, everyone's code can only handle non-negative floating-point numbers. The next step should be to think about how to handle pure negative numbers and mixed positive/negative cases, so that the code can truly handle all floating-point numbers.
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
Floor 56 Posted 2006-10-11 01:33 ·  中国 湖南 娄底 新化县 电信
银牌会员
★★★
Credits 1,218
Posts 485
Joined 2006-07-21 21:24
19-year member
UID 58987
From 湖南.娄底
Status Offline
After testing, the code in my 47th-floor post and moderator namejm's code no longer have any problems.

This problem has been solved perfectly. Not only can it handle floating-point operations, it also solves the digit-limit restriction of batch arithmetic (I found many calculators have digit limits; the calculator that comes with Windows can only calculate 31 digits. Looks like our script can really play to its strengths in this area, haha~~~!)

I was just thinking of merging this unlimited addition/subtraction code; the code is being written ing... It will be posted in my real-number arithmetic script thread!
Floor 57 Posted 2006-10-11 02:09 ·  中国 甘肃 兰州 电信
金牌会员
★★★★
Credits 4,103
Posts 1,744
Joined 2006-01-20 13:00
20-year member
UID 49241
Gender Male
From 甘肃.临泽
Status Offline
Impressive, impressive~~
Floor 58 Posted 2006-10-11 02:46 ·  中国 四川 南充 电信
超级版主
★★★★
我爱DOS
Credits 5,310
Posts 2,044
Joined 2005-09-26 12:00
20-year member
UID 42843
Gender Male
From 四川南充
Status Offline
Finally solved the character-digit limit on floating-point arithmetic; in theory it can calculate values in an N-digit range.
Extract the integer and fractional parts of the two numbers separately
Pad the fractional part with 0s on the low end so that the digits of the two numbers line up
Starting from the lowest fractional digit, calculate the sum of the two numbers one digit at a time; if it exceeds 9, carry 1 to the next higher digit, until the highest integer digit
(The calculation in the 47th-floor post gives an error for decimals with 2 decimal points,
32165.464.1654 +1321.654.31654 =33487.1118
The calculation in the 50th-floor post also gives an error when the first character is a decimal point,
Please enter the first number:.31654
Please enter the second number:1.31654
Operand missing.
The syntax of the command is incorrect.)
Neither of those two problems exists in this code. The code in the 47th-floor and 50th-floor posts still needs improvement.
@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 "^*$">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 ]
Recent Ratings for This Post ( 1 in total) Click for details
RaterScoreTime
+4 2006-10-14 10:13
Attachments
实数计算脚本.rar (834 bytes, Credits to download 1 pts, Downloads: 9)
Floor 59 Posted 2006-10-11 02:47 ·  中国 四川 南充 电信
超级版主
★★★★
我爱DOS
Credits 5,310
Posts 2,044
Joined 2005-09-26 12:00
20-year member
UID 42843
Gender Male
From 四川南充
Status Offline
Originally posted by pengfei at 2006-10-11 01:33:
After testing, the code in my 47th-floor post and moderator namejm's code no longer have any problems.

This problem has been solved perfectly. Not only can it handle floating-point operations, it also solves the digit-limit restriction of batch arithmetic (发砮..

Both of your code versions still have some problems! Look at mine!
Floor 60 Posted 2006-10-11 02:52 ·  中国 甘肃 兰州 电信
金牌会员
★★★★
Credits 4,103
Posts 1,744
Joined 2006-01-20 13:00
20-year member
UID 49241
Gender Male
From 甘肃.临泽
Status Offline
Originally posted by qwe1234567 at 2006-10-11 02:46:
Finally solved the character-digit limit on floating-point arithmetic; in theory it can calculate values in an N-digit range.
Extract the integer and fractional parts of the two numbers separately
Pad the fractional part with 0s on the low end so that the two numbers ...

The calculation result is:
0.9999999999999999999999999999999999999999999999999999999999999+0.77777777777777
7=177.7777769777777769999999999999999999999999999999999999999999999
Press any key to continue . . .
???
Forum Jump: