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:33
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » [Joint Participation] [Challenge Ideas] [Batch Processing Floating-Point Operations] DigestI View 41,148 Replies 136
Original Poster Posted 2006-10-04 04:10 ·  中国 北京 联通
金牌会员
★★★★
Credits 2,902
Posts 1,147
Joined 2006-09-21 12:00
19-year member
UID 63324
Gender Male
Status Offline
) This post is meant to throw out a brick to attract jade; everyone expand your thinking and interactively take part in learning batch files together~ :)

) [Using DOS internal commands to calculate the sum of two floating-point numbers]

  Example: Sum.Bat 12.99 438.76
  Result: 451.75

  Rules: Negative numbers are not considered
      Possible errors from deliberately or accidentally entering non-numeric characters are not considered for now
      Only DOS internal commands may be used (no DOS version restriction); external commands are forbidden.
      Only consider adding the two floating-point numbers appearing in %1 and %2; adding more floating-point numbers is not considered for now.
      Allowed number formats: 0.91 0.10  2.12 1092.90
      Formats not allowed for now: .91  .9
      (Decimal precision: two digits after the decimal point)

  Purpose: Broaden thinking, increase interest in batch files, increase everyone’s interactive learning and hands-on playing,
      through our continuous interaction, let everyone participate and progress together in the use of batch files :)

  Direction: This is only one item; more content needs to be discovered together by netizens, with moderator support :)
      Everyone can use any wild idea whatsoever to implement the problem above~ :)


  Why this post exists: Only with interaction and everyone participating can one’s own level improve faster.
            Turn the way of asking only when encountering problems and not actively learning batch files normally into everyone actively improving together step by step :)


  Reward: For excellent solutions and solutions with different lines of thought, the moderators will give godlike guidance and demonstrations,
      then give everyone points as encouragement~ :)

  Other: Waiting for everyone to have better ideas and very practical topics for interactive learning and application, with everyone participating together :)
===================================
Recent Ratings for This Post ( 1 in total) Click for details
RaterScoreTime
vsbat +1 2010-05-30 23:44
Floor 2 Posted 2006-10-04 04:20 ·  中国 四川 成都 教育网
铂金会员
★★★★
Credits 7,493
Posts 2,672
Joined 2005-09-02 00:00
20-year member
UID 42173
Gender Male
Status Offline

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 3 Posted 2006-10-04 04:31 ·  中国 北京 联通
金牌会员
★★★★
Credits 2,902
Posts 1,147
Joined 2006-09-21 12:00
19-year member
UID 63324
Gender Male
Status Offline
Originally posted by electronixtar at 2006-10-4 04:20:

@echo off
echo wscript.echo CDbl(WScript.Arguments(0))+CDbl(WScript.Arguments(1))> tmp.vbe
cscript //noLogo tmp.vbe %1 %2
del tmp.vbe


^_^



Wonderful~~ Added 6 points~ :)

C:\TEMP>a.bat 12.99 438.76
451.75
Floor 4 Posted 2006-10-04 04:47 ·  中国 湖南 娄底 新化县 电信
银牌会员
★★★
Credits 1,218
Posts 485
Joined 2006-07-21 21:24
19-year member
UID 58987
From 湖南.娄底
Status Offline
The code in the first section of this post is the latest modification. It is more powerful; everyone is welcome to test it...


Integer/floating-point segmented calculation code:
In general, the integer part can calculate up to 9 digits, and the decimal part can calculate up to 9 digits.
The decimal part and integer part together can calculate up to 18 digits.
Otherwise it will overflow or be an invalid number...

The functions of this script:
1. It can calculate any real-number value.
2. It has the function of judging erroneous input. For example, if there are illegal characters in the operands, or if the number of characters exceeds the script’s calculation range, it will prompt you to enter again.
3. It solves the radix error problem.
4. Formatted output of calculation results.

@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
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_%
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%
if %countx% gtr 9 goto error
if %countx_% gtr 9 goto error
set after=0
set front=
if %county% lss %county_% (
set count=%county_%
set /a result=%county_%-%county%
call :fine !result! %two%
set two=!incept!
) else (
set count=%county%
set /a result=%county%-%county_%
call :fine !result! %two_%
set two_=!incept!
)
call :omit %two%
set two=%want%
call :omit %two_%
set two_=%want%
call :go %two%
set county=%wish%
call :go %two_%
set county_=%wish%
if %county% gtr 9 goto error
if %county_% gtr 9 goto error
if "%one%"=="" set one=0
if "%one_%"=="" set one_=0
if "%two%"=="" set two=0
if "%two_%"=="" set two_=0
set /a decimal=%two%+%two_%
set carry=0!decimal:~0,-%count%!
set decimal=!decimal:~-%count%!
set refer=%decimal%
call :go %refer%
set countz=%wish%
set /a spare=%count%-%countz%
set after=
set front=0
call :fine %spare% %decimal%
set decimal=%incept%
set /a integer=%one%+%one_%+%carry%
set dot=.
call :raze %decimal%
set decimal=%want_%
if "%decimal%"=="" set dot=
cls
echo ============
echo Calculation result!
echo ============
echo.
echo %num1%+%num2%=%integer%%dot%%decimal%
pause >nul
goto :eof

: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 Sorry, your input has the following two kinds of errors:
echo.
echo 1. Illegal characters other than Arabic numerals were entered.
echo.
echo 2. The integer or decimal digit count exceeded 9 digits.
echo.
echo ========================================================
echo.
echo.
echo Press any key to enter again...
pause >nul
goto input




The section below is also general-purpose, but the decimal part can only calculate 8 digits, and it does not have the function of judging erroneous input or judging whether the entered value meets the requirements.



Integer/floating-point segmented calculation code:
The integer part can calculate up to 9 digits, and the decimal part can calculate up to 8 digits.
The decimal part and integer part together can calculate up to 17 digits.
Otherwise it will overflow or be an invalid number...

It can calculate any type of value; floating-point values are no longer restricted by digit count.
It solves the radix error problem that occurs when the first decimal digit is zero and is followed by an 8 or 9.
Formatted output of calculation results!

This section of code is already general-purpose. Everyone is welcome to test it...

@echo off
set /p number1=Please enter operand one:
set /p number2=Please enter operand two:
echo %number1% | find "." >nul || set number1=%number1%.0
echo %number2% | find "." >nul || set number2=%number2%.0
if "%number1:~-1%"=="." set number1=%number1%0
if "%number2:~-1%"=="." set number2=%number2%0
if "%number1:~0,1%"=="." set number1=0%number1%
if "%number2:~0,1%"=="." set number2=0%number2%
setlocal enabledelayedexpansion
for %%a in (%number1% %number2%) 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 :go %two%
set count=%wish%
call :go %two_%
set count_=%wish%
if %count% lss %count_% (
set /a result=%count_%-%count%
call :fine !result! %two%
set two=!incept!
) else (
set /a result=%count%-%count_%
call :fine !result! %two_%
set two_=!incept!
)
if "%one%"=="" set one=0
if "%one_%"=="" set one_=0
set /a integer=%one%+%one_%
set /a decimal=1%two%+1%two_%
if "%decimal:~0,1%"=="2" (
set decimal=%decimal:~1%
) else (
set decimal=%decimal:~1%
set /a integer=%integer%+1
)
:raze
if "!decimal:~-1!"=="0" (
set decimal=!decimal:~0,-1!
goto raze
)
if "%decimal%"=="" (
set dot=
) else (
set dot=.
)
echo %integer%%dot%%decimal%
pause
exit

:go
set remove=%1
set wish=0
:go_
if not "!remove:~0,1!"=="~" (
for /l %%c in (0,1,9) do (
if "!remove:~0,1!"=="%%c" (
set /a wish+=1
set remove=!remove:~1!
goto go_
)
)
)
goto :eof
:fine
set take=%1
set incept=%2
:fine_
if not "%take%"=="0" (
set /a take-=1
set incept=!incept!0
goto fine_
)
goto :eof
:omit
set want=%1
:again
if "%want:~0,1%"=="0" (
set want=%want:~1%
goto again
)
goto :eof



Related problem discussion: About the radix problem during numerical calculations!

[ Last edited by pengfei on 2006-10-9 at 05:01 ]
Floor 5 Posted 2006-10-04 05:12 ·  中国 北京 联通
金牌会员
★★★★
Credits 2,902
Posts 1,147
Joined 2006-09-21 12:00
19-year member
UID 63324
Gender Male
Status Offline
Addictive!!! Added 6 points for brother pengfei~ :)


C:\TEMP>b.bat 12.99 438.76
451.75
Press any key to continue. . .
Floor 6 Posted 2006-10-04 05:18 ·  中国 北京 联通
金牌会员
★★★★
Credits 2,902
Posts 1,147
Joined 2006-09-21 12:00
19-year member
UID 63324
Gender Male
Status Offline
The works by the two experts are very wonderful~~
Personally I feel that to learn batch files and DOS batch files well, as well as the application of scripts,
is actually equivalent to walking step by step toward the road of programming :)

Or developers use a kind of program thinking and a way of understanding data structures to bring batch files to a higher level :)

This is one of the reasons why many netizens, after learning DOS batch file applications,
still cannot improve any further after many years :)

But some experts really are moving upward every day and every step,
skills are no longer important; the data structures applied can solve many problems :)
Whether in batch files or in code development, they are all connected :)

[ Last edited by redtek on 2006-10-4 at 05:21 ]
Floor 7 Posted 2006-10-04 10:15 ·  中国 湖南 娄底 新化县 电信
银牌会员
★★★
Credits 1,218
Posts 485
Joined 2006-07-21 21:24
19-year member
UID 58987
From 湖南.娄底
Status Offline
Finally solved the limitation on decimal digit count; it can calculate various types of values, and the number of decimal digits is not restricted. The problem of erroneous input has not been solved for now.

The code is updated on the 4th floor!
Floor 8 Posted 2006-10-04 11:18 ·  中国 广东 佛山 广东睿江科技有限公司
荣誉版主
★★★★
batch fan
Credits 5,226
Posts 1,737
Joined 2006-03-10 00:38
20-year member
UID 51697
From 成都
Status Offline
  Posting a section of code. In the rush I did not have time to do error-checking on the data or optimize the code; it can adapt to cases where the number of decimal digits is inconsistent. The basic idea is to calculate the integer part and decimal part of the value separately:

@echo off
cls
set input1=
set input2=
set /p input1=Please enter the first value:
set /p input2=Please enter the second value:
setlocal enabledelayedexpansion
for /f "tokens=1-4 delims=." %%i in ("%input1%.%input2%") do (
set num1=%%i
set num2=%%j
set num3=%%k
set num4=%%l
set length=0
call :get_length %%j
set length1=!length!
echo !length1!
set length=0
call :get_length %%l
set length2=!length!
echo !length2!
call :add_zero
set /a sum1=!num1!+!num3!
set /a sum2=!num2!+!num4!
call :set_num
if !sum2! geq !str! set /a sum2=!sum2!-!str! & set /a sum1=!sum1!+1
echo !sum1!.!sum2!
)
pause
goto :eof

:get_length
for /f %%i in ("%1") do (
set /a length+=1
set var=%%i
if not "!var!"=="" set var=!var:~0,-1!&& call :get_length !var!
)
goto :eof

:add_zero
set /a cha=%length1%-%length2%
set cha=%cha:-=%
if %cha% gtr 0 (
for /l %%i in (1,1,%cha%) do set str=!str!0
echo !str!
if %length1% gtr %length2% (set num4=%num4%!str!) else (set num2=%num2%!str!)
)
echo %num2% %num4%
goto :eof

:set_num
if %length1% geq %length2% (set longer=%length1%) else (set longer=%length2%)
set str=
for /l %%i in (1,1,%longer%) do set str=!str!0
set str=1%str%
echo %str%
goto :eof


[ Last edited by namejm on 2006-10-4 at 11:20 ]
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
Floor 9 Posted 2006-10-04 20:17 ·  中国 四川 成都 教育网
铂金会员
★★★★
Credits 7,493
Posts 2,672
Joined 2005-09-02 00:00
20-year member
UID 42173
Gender Male
Status Offline
Scripts are still simpler ^_^

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 10 Posted 2006-10-04 23:50 ·  中国 湖南 娄底 电信
银牌会员
★★★
Credits 1,218
Posts 485
Joined 2006-07-21 21:24
19-year member
UID 58987
From 湖南.娄底
Status Offline
Solved the problem where the first digit after the decimal point is 0 and an 8 or 9 appears after it, causing the value to be an invalid number.

A brand-new algorithm; the rough idea is: read the decimal digit count and pad zeros where insufficient. After removing the . sign, calculate the decimal and integer parts together, and after the calculation is complete, accurately insert the decimal point into the corresponding place according to the recorded decimal point position, thereby completing the floating-point value calculation.

This section of code has better generality; time was tight and I did not have time to optimize it:


Integer/floating-point merged calculation code:
The integer part can calculate up to 8 digits, and the decimal part can calculate up to 8 digits.
The decimal part and integer part together can calculate up to 9 digits
Otherwise it will overflow or be an invalid number...

Using a digit-by-digit loop zero-removal method to solve the problem of the highest digit being zero or multiple zeros; you can test numerical calculations of (0.0 .23 12. .).
Solved radix problems such as (0.0+0.0289), (0.08+1.029).
Current testing can adapt to various situations.
Looking forward to everyone doing comprehensive testing...

@echo off
set /p number=Please enter operand one:
set /p number_=Please enter operand two:
call :omit %number%
set number=%want%
call :omit %number_%
set number_=%want%
echo %number% | find "." >nul || set number=%number%.0
echo %number_% | find "." >nul || set number_=%number_%.0
if "%number:~-1%"=="." set number=%number%0
if "%number_:~-1%"=="." set number_=%number_%0
if "%number:~0,1%"=="." set number=0%number%
if "%number_:~0,1%"=="." set number_=0%number_%
setlocal enabledelayedexpansion
for %%a in (%number% %number_%) 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 :go %two%
set num1=%wish%
call :go %two_%
set num2=%wish%
if %num1% lss %num2% (
set note=%num2%
set /a result=%num2%-%num1%
call :fine !result! %two%
set two=!incept!
) else (
set note=%num1%
set /a result=%num1%-%num2%
call :fine !result! %two_%
set two_=!incept!
)
set term=0
if %one:~0,1%==0 set one=!one:~1!
if %one_:~0,1%==0 set one_=%one_:~1%
if "%one%"=="" (
set one=1
set /a term+=1
)
if "%one_%"=="" (
set one_=1
set /a term+=1
)
set /a fruit_=%one%%two%+%one_%%two_%
set fruit_=:%fruit_%
:insert
if not "!fruit_:~-1!"==":" (
if "!num_!"=="%note%" (
set fruit=.!fruit!
set /a ii=!fruit_:~1!-%term%
set fruit_=:!ii!
)
set fruit=!fruit_:~-1!!fruit!
set fruit_=!fruit_:~0,-1!
set /a num_+=1
goto insert
)
echo %fruit%
pause
exit

:go
set remove=%1
set wish=0
:go_
if not "!remove:~0,1!"=="~" (
for /l %%c in (0,1,9) do (
if "!remove:~0,1!"=="%%c" (
set /a wish+=1
set remove=!remove:~1!
goto go_
)
)
)
goto :eof
:fine
set take=%1
set incept=%2
:fine_
if not "%take%"=="0" (
set /a take-=1
set incept=!incept!0
goto fine_
)
goto :eof
:omit
set want=%1
:again
if "%want:~0,1%"=="0" (
set want=%want:~1%
goto again
)
goto :eof


[ Last edited by pengfei on 2006-10-6 at 03:51 ]
Floor 11 Posted 2006-10-05 00:44 ·  中国 广东 佛山 广东睿江科技有限公司
荣誉版主
★★★★
batch fan
Credits 5,226
Posts 1,737
Joined 2006-03-10 00:38
20-year member
UID 51697
From 成都
Status Offline
  The code by pengfei on the “10th floor” first pads the floating-point numbers with 0 to make the digit counts equal, then removes the decimal point, processes the new number, and then restores the decimal point position. This idea is quite novel and goes one step beyond my idea on the “8th floor”. After optimization, the code will be more concise than my section. It seems that lots of discussion really can easily spark flashes of wisdom ^_^
尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
Floor 12 Posted 2006-10-05 01:43 ·  中国 湖南 娄底 电信
银牌会员
★★★
Credits 1,218
Posts 485
Joined 2006-07-21 21:24
19-year member
UID 58987
From 湖南.娄底
Status Offline
^_^ Hehe~ Brother namejm’s code idea on the 8th floor is the same as mine on the 4th floor. If the first decimal digit is zero and followed by 8 or 9, an error will occur; it is still a radix problem, while the code on the 10th floor will not.
Floor 13 Posted 2006-10-05 04:44 ·  中国 四川 南充 电信
超级版主
★★★★
我爱DOS
Credits 5,310
Posts 2,044
Joined 2005-09-26 12:00
20-year member
UID 42843
Gender Male
From 四川南充
Status Offline
I tried it; if the first digit is 0, any 8 or 9 after it will cause an error! Even the 10th floor’s is the same!
Floor 14 Posted 2006-10-05 04:49 ·  中国 湖南 娄底 电信
银牌会员
★★★
Credits 1,218
Posts 485
Joined 2006-07-21 21:24
19-year member
UID 58987
From 湖南.娄底
Status Offline
Moderator, you are adding zero to the highest digit of the integer, right!

Try adding zero to the first digit after the decimal point, then compare the calculation results of the two code sections.
Floor 15 Posted 2006-10-05 05:09 ·  中国 四川 南充 电信
超级版主
★★★★
我爱DOS
Credits 5,310
Posts 2,044
Joined 2005-09-26 12:00
20-year member
UID 42843
Gender Male
From 四川南充
Status Offline
The one below automatically removes 0 when the first digit is 0, automatically adds 0 when there is no digit before the decimal point, and automatically removes 0 when there is 0 at the end of the decimal part!
@echo off
if not %1*==* (set number=%1&set number_=%2&goto bj)
set /p number=Please enter operand one:
set /p number_=Please enter operand two:
:bj
echo %number% | find "." >nul || set number=%number%.0
echo %number_% | find "." >nul || set number_=%number_%.0
if %number:~0,1%==. set number=0%number%
if %number_:~0,1%==. set number_=0%number_%
if "%number:~-1%"=="." set number=%number%0
if "%number_:~-1%"=="." set number_=%number_%0
setlocal enabledelayedexpansion
for %%a in (%number% %number_%) 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 :go %two%
set num1=%wish%
call :go %two_%
set num2=%wish%
if %num1% lss %num2% (
set note=%num2%
set /a result=%num2%-%num1%
call :fine !result! %two%
set two=!incept!
) else (
set note=%num1%
set /a result=%num1%-%num2%
call :fine !result! %two_%
set two_=!incept!
)
:1
set n1=0
if "!one:~0,1!"=="0" set one=!one:~1!&&goto 1
if %two:~0,1%==0 set two=1%two%&&set n1=1
:2
if "!one_:~0,1!"=="0" set one_=!one_:~1!&&goto 2
if %two_:~0,1%==0 set two_=1%two_%&&set/a n1+=1
set /a num2=%two%+%two_%
set/a n1=!num2:~0,-%note%!-%n1%
set num2=!num2:~-%note%!
set /a num1=%one%+%one_%+%n1%
:3
if !num2:~-1!==0 set num2=!num2:~0,-1!&&goto 3
if %num2%*==* (echo %num1%) ELSE echo %num1%.%num2%
PAUSE
goto :eof

:go
set remove=%1
set wish=0
:go_
if not "!remove:~0,1!"=="~" (
for /l %%c in (0,1,9) do (
if "!remove:~0,1!"=="%%c" (
set /a wish+=1
set remove=!remove:~1!
goto go_
)
)
)
goto :eof
:fine
set take=%1
set incept=%2
:fine_
if not "%take%"=="0" (
set /a take-=1
set incept=!incept!0
goto fine_
)
goto :eof


[ Last edited by qwe1234567 on 2006-10-6 at 07:40 ]
Recent Ratings for This Post ( 1 in total) Click for details
RaterScoreTime
+4 2006-10-14 10:14
1 2 3 10 Next ›
Forum Jump: