I need to find the smallest number and print the smallest and the others in bat - batch-file

i neeed to Write a bat file that accepts three parameters. Of these three parameters, find the smallest one, then display all the numbers from 1 to AND the smallest parameter on the screen.
i tried this but it does not work
#ECHO OFF
set /a c=%1
set /a b=%2
set /a a=%3
set Smallest=%d%
if %c% lss %Smallest% set Smallest=%c%
if %b% lss %Smallest% set Smallest=%b%
if %a% lss %Smallest% set Smallest=%a%
Echo Smallest number is %Smallest%
pause>nul

This is the way I would do it:
#echo off
setlocal
set /A c=%1, b=%2, a=%3
set /A "comp=((a-b)>>31)+1,one=!comp*a+comp*b,comp=((one-c)>>31)+1,Smallest=!comp*one+comp*c"
echo Smallest: %Smallest%
for /L %%i in (1,1,%Smallest%) do echo %%i
That is, if a > b then (a-b) is positive or zero (else, is negative), and (a-b)>>31 is zero (else, is -1 because >> is a signed shift of 31 bits) so finally ((a-b)>>31)+1 is one if a > b or is zero if a < b. In this way, we use this value comp to get b, or not this value !comp! to get a; and store the lesser of both in one variable.
The same method is used to get the lesser of one and c.
At end, we show all values from 1 to the lesser...

Here is an example code for this homework which outputs the smallest number and all numbers from 1 to the smallest number if the smallest number is not less than 1.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "Smallest=%~1"
if not defined Smallest goto OutputHelp
if "%~2" == "" goto OutputHelp
for %%I in (%*) do if %%~I LSS %Smallest% set "Smallest=%%~I"
echo The smallest number is: %Smallest%
echo/
if %Smallest% GEQ 1 (
for /L %%I in (1,1,%Smallest%) do echo %%I
) else (
for /L %%I in (1,-1,%Smallest%) do echo %%I
)
goto EndBatch
:OutputHelp
echo %~nx0 must be run with at least two integer numbers as arguments.
echo/
echo Example: %~nx0 489 0x2AF 0715
echo/
echo An integer number beginning with 0x is interpreted hexadecimal.
echo An integer number beginning with 0 is interpreted as octal number
echo which cannot contain the digits 8 and 9 to be valid. An invalid
echo octal number is interpreted with value 0.
echo/
echo There is not checked if an argument string is a valid string for
echo a decimal, hexadecimal or octal integer number in the value
echo range -2147483648 to 2147483647 (32 bit signed integer).
:EndBatch
echo/
pause
endlocal
The output of this batch file on running it with the three numbers of the example without the output of all numbers from 1 to smallest number is:
The smallest number is: 0715
The octal number 0715 is decimal 461 and the hexadecimal number 0x2AF is decimal 687 which makes the octal number 0715 the smallest number.
To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.
call /?
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
set /?
setlocal /?
I recommend to read also:
Safe number comparison in Windows batch file
Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files
Why is no string output with 'echo %var%' after using 'set var = text' on command line?
DosTips forum topic: ECHO. FAILS to give text or blank line - Instead use ECHO/

Related

Update running unsigned long long sum in bat file

Is there a simple way to sum two numbers potentially >= 2*31 in a .BAT file?
I have a running sum, and argument %1 that is the name of an existing file.
set sum=4123456789
set fsize=%~z1
I'd like to add fsize to sum. Unfortunately fsize (and sum) can be as tiny as zero or 10's of gigabytes (%~z1 accurately reports >= 2*31 file sizes).
I know a program could do it, and I'll go that route if necessary, but I'd prefer to do it with a few added lines of .BAT logic.
I think the easiest way is to split the summands into two parts – integer and fractional Gigas (multiples of 1000000000), add the respective parts individually, then recombine them. See the following example script, which contains a lot of explanatory remarks:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Initialise variables:
set /A "GIGASUM=0, FRACSUM=0"
:LOOP
rem // Get command line argument:
shift
set "NUM=%~0"
if not defined NUM goto :NEXT
rem // Check number for validity:
(for /F "delims=0123456789" %%N in ("%NUM%") do rem/) && (
echo ERROR: non-numeric characters encountered!
exit /B 1
)
rem // Split number into two parts, integer and fractional Gigas:
set "NUM=000000000%NUM%"
set "GIGA=%NUM:~,-9%" & set "FRAC=%NUM:~-9%"
rem // Remove leading zeros from integer Gigas:
for /F "tokens=* delims=0" %%N in ("%GIGA%") do set "GIGA=%%N"
rem // Sum up fractional Gigas and determine carry:
set /A "FRACSUM+=(1%FRAC%-1000000000)"
set "CARRY=%FRACSUM:~,-9%" & set "FRACSUM=000000000%FRACSUM%"
set "FRACSUM=%FRACSUM:~-9%"
rem // Sum up integer Gigas and regard carry:
set /A "GIGASUM+=GIGA+CARRY"
rem // Loop back to next summand:
goto :LOOP
:NEXT
rem // Remove leading zeros:
for /F "tokens=* delims=0" %%N in ("%GIGASUM%%FRACSUM%") do set "SUM=%%N"
if not defined SUM set "SUM=0"
rem // Return resulting sum:
echo %SUM%
endlocal
exit /B
The greatest possible sum amounts to 231 * 109 – 1 = 2147483647999999999, an overflow is not detected.
The required logic is not so complicated. Here it is one version:
#echo off
setlocal
:loop
set /p "pair=Enter two numbers separated by plus sign: "
if errorlevel 1 goto :EOF
for /F "tokens=1,2 delims=+" %%a in ("%pair%") do set "num1=%%a" & set "num2=%%b"
set "sum="
set "carry=0"
:nextDigit
set /A sum1=%num1:~-1%+%num2:~-1%+carry
set "sum=%sum1:~-1%%sum%"
set /A carry=sum1/10
set "num1=%num1:~0,-1%"
if not defined num1 set "num1=0"
set "num2=%num2:~0,-1%"
if not defined num2 set "num2=0"
if "%carry%%num1%%num2%" neq "000" goto nextDigit
echo The sum is: %sum%
goto loop

Batch file multiply positive variables return a negative number

I've been working on a Batch polygon area calculator and I got a problem.
I need to multiply 2 variables, but sometimes it return a negative number if the two positive variables are large.
Here's an example: 999999*999999 returns -729379967.
Code goes below:
REM Calc square area
:PolySqu
Cls
Echo Polygon Area Calculator
For /L %%P In (1,1,57) Do Echo.
Set /P "InputPolygonCalSqu=Enter one of the line's length in cm :"
Set /A SquArea=InputPolygonCalSqu * InputPolygonCalSqu
Cls
Echo Polygon Area Calculator
For /L %%P In (1,1,57) Do Echo.
Echo The area of this square is %SquArea% cm2.
Pause
Goto :PolygonCal
It seemed the command
Set /A SquArea="InputPolygonCalSqu * InputPolygonCalSqu
doesn't calculate properly.
As others already pointed out, a batch-file natively supports 32-bit signed integer arithmetics only.
The following code constitutes a work-around for multiplying non-negative numbers greater than the limit of 232 − 1 = 2147483647, using pure batch-file commands (let us call it multiply.bat):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define arguments here:
set "NUM1=%~1"
set "NUM2=%~2"
set "NUM3=%~3"
set "NUM4=%~4"
if defined NUM1 set "NUM1=%NUM1:"=""%
if defined NUM2 set "NUM2=%NUM2:"=""%
if defined NUM3 set "NUM3=%NUM3:"=%
call :VAL_ARGS NUM1 NUM2 NUM4 || exit /B 1
rem // Define constants here:
set /A "DIG=4" & set "PAD="
setlocal EnableDelayedExpansion
for /L %%J in (1,1,%DIG%) do set "PAD=!PAD!0"
endlocal & set "PAD=%PAD%"
rem // Determine string lengths:
call :STR_LEN LEN1 NUM1
call :STR_LEN LEN2 NUM2
set /A "LEN1=(LEN1-1)/DIG*DIG"
set /A "LEN2=(LEN2-1)/DIG*DIG"
set /A "LIM=LEN1+LEN2+DIG"
for /L %%I in (0,%DIG%,%LIM%) do set /A "RES[%%I]=0"
rem // Perform block-wise multiplication:
setlocal EnableDelayedExpansion
for /L %%J in (0,%DIG%,%LEN2%) do (
for /L %%I in (0,%DIG%,%LEN1%) do (
set /A "IDX=%%I+%%J"
if %%I EQU 0 (set "AUX1=-%DIG%") else (
set /A "AUX1=%DIG%+%%I" & set "AUX1=-!AUX1!,-%%I"
)
if %%J EQU 0 (set "AUX2=-%DIG%") else (
set /A "AUX2=%DIG%+%%J" & set "AUX2=-!AUX2!,-%%J"
)
for /F "tokens=1,2" %%M in ("!AUX1! !AUX2!") do (
set "AUX1=!NUM1:~%%M!" & set "AUX2=!NUM2:~%%N!"
)
call :NO_LEAD0 AUX1 !AUX1!
call :NO_LEAD0 AUX2 !AUX2!
set /A "RES[!IDX!]+=AUX1*AUX2"
set /A "NXT=IDX+DIG, DIT=DIG*2"
for /F "tokens=1,2,3" %%M in ("!IDX! !NXT! !DIT!") do (
set "AUX=!RES[%%M]:~-%%O,-%DIG%!"
set /A "RES[%%N]+=AUX"
set "RES[%%M]=!RES[%%M]:~-%DIG%!"
call :NO_LEAD0 RES[%%M] !RES[%%M]!
)
)
)
rem // Build resulting product:
set "RES=" & set "AUX="
for /L %%I in (0,%DIG%,%LIM%) do (
set /A "RES[%%I]+=AUX"
set /A "NXT=%%I+DIG"
for /L %%J in (!NXT!,%DIG%,!NXT!) do (
set "AUX=!RES[%%I]:~-%%J,-%DIG%!"
)
set "RES[%%I]=%PAD%!RES[%%I]!"
set "RES=!RES[%%I]:~-%DIG%!!RES!"
)
endlocal & set "RES=%RES%"
call :NO_LEAD0 RES %RES%
rem // Return resulting product:
echo(%RES%
if defined NUM3 (
endlocal
set "%NUM3%=%RES%"
) else (
endlocal
)
exit /B
:NO_LEAD0 rtn_var val_num
rem // Remove leading zeros from a number:
for /F "tokens=* delims=0" %%Z in ("%~2") do (
set "%~1=%%Z" & if not defined %~1 set "%~1=0"
)
exit /B 0
:STR_LEN rtn_length ref_string
rem // Retrieve length of string:
setlocal EnableDelayedExpansion
set "STR=!%~2!"
if not defined STR (set /A LEN=0) else (set /A LEN=1)
for %%L in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if defined STR (
set "INT=!STR:~%%L!"
if not "!INT!"=="" set /A LEN+=%%L & set "STR=!INT!"
)
)
endlocal & set "%~1=%LEN%"
exit /B 0
:VAL_ARGS ref_arg1 ref_arg2 ref_arg3
rem // Check arguments for validity:
if not defined %~1 >&2 echo ERROR: too few arguments given! & exit /B 1
if not defined %~2 >&2 echo ERROR: too few arguments given! & exit /B 1
if defined %~3 >&2 echo ERROR: too many arguments given! & exit /B 1
(call echo "%%%~1%%" | > nul findstr /R /C:"^\"[0-9][0-9]*\" $") || (
>&2 echo ERROR: argument 1 is not purely numeric! & exit /B 1
)
(call echo "%%%~2%%" | > nul findstr /R /C:"^\"[0-9][0-9]*\" $") || (
>&2 echo ERROR: argument 2 is not purely numeric! & exit /B 1
)
exit /B 0
To use it provide the two numbers to multiply as command line arguments; for instance:
multiply.bat 999999 999999
The resulting product is returned on the console:
999998000001
If you provide a third argument, the product is assigned to a variable with that name; for example:
multiply.bat 999999 999999 SquArea
This sets variable SquArea to the resulting value. The latter is also still returned on the console.
To silently assign the variable without any additional console output, redirect it to the nul device:
multiply.bat 999999 999999 SquArea > nul
Batch uses 32bit integers for storing numbers. This gives them a maximum size of 2^31 - 1 = 2,147,483,647.
999,999 * 999,999 = 999,998,000,001 which is larger than 2,147,483,647 therefore it "wraps" and starts from negatives.
This is a limitation of batch although there are some workarounds.
This might be useful
Can batch files not process large numbers?
The largest number batch can take is 2^31 - 1 = 2,147,483,647.
So again, it is starting back from negative and giving you that answer..
I noticed using pure batch, it would be somewhat to very difficult to implement operations that support the numbers beyond the 32-bit integer limit. So instead, I limited the numbers, so they won't overflow when multiplied.
REM Calc Square Area
:PolySqu
Cls
Echo Polygon Area Calculator
For /L %%P In (1,1,57) Do Echo.
Set /P "InputPolygonCalSqu=Enter one of the line's length in cm [Less then 40000] :"
If %InputPolygonCalSqu% GTR 40000 Goto :PolySqu
Set /A SquArea="InputPolygonCalSqu * InputPolygonCalSqu
Cls
Echo Polygon Area Calculator
For /L %%P In (1,1,57) Do Echo.
Echo The area of this square is %SquArea% cm2.
Pause
Goto :PolygonCal

How to count the ones in a binary representation of a given hex in a cmd Batch?

i am trying to write a batch file that asks the user to type a hexadcimal number and then counts the number of ones in the binary representation , like if i typed A the program echos 1 .
i have this code that uses a look up table to convert from binary to hex and answered by Aacini here ...
#echo off
setlocal
set "bin=110111101010110110111110111011111100101011111110"
call :bin2hex hex=%bin%
echo hex: %hex%
goto :EOF
:bin2hex hexVar=binValue
setlocal EnableDelayedExpansion
for %%a in (0000-0;0001-1;0010-2;0011-3;0100-4;0101-5;0110-6;0111-7;1000-8;1001-9;1010-A;1011-B;1100-C;1101-D;1110-E;1111-F) do (
for /F "tokens=1,2 delims=-" %%b in ("%%a") do (
set "hextable[%%b]=%%c"
)
)
set "hex="
set "bin=000%~2"
:bin2hexloop
set "hex=!hextable[%bin:~-4%]!%hex%"
set "bin=%bin:~0,-4%"
if defined bin if "%bin:~3%" neq "" goto bin2hexloop
endlocal & set "%~1=%hex%"
goto :EOF
i tried to inverse the way this code works , but it didn't work !
here is my attempt
#echo off
setlocal
set "hex=ABCDEF"
call :hex2bin bin=%bin%
echo : %bin%
pause;
goto :EOF
:hex2bin binVar=hexValue
setlocal EnableDelayedExpansion
for %%a in (0-0000;1-0001;2-0010;3-0011;4-0100;5-0101;6-0110;7-0111;8-1000;9-1001;A-1010;B-1011;C-1100;D-1101;E-1110;F-1111) do (
for /F "tokens=1,2 delims=-" %%b in ("%%a") do (
set "bintable[%%b]=%%c"
)
)
set "bin="
set "hex=000%~16"
:hex2binloop
set "bin=!bintable[%hex:~-4%]!%bin%"
set "hex=%hex:~0,-4%"
if defined hex if "%hex:~3%" neq "" goto hex2binloop
endlocal & set "%~4=%bin%"
goto :EOF
anybody can help me ?
If I understood you correctly, you want not to "convert a hexadecimal number to binary", but to "count the ones that each hex digit have" and accumulate they (for example, for A the number is 1). This way, the solution must work with "The number of ones each hex digit have".
#echo off
setlocal
set "hex=ABCDEF"
call :countOnesInHex ones=%hex%
echo There are %ones% ones in %hex%
pause
goto :EOF
:countOnesInHex ones=hexValue
setlocal
for %%a in (0-0;1-1;2-1;3-2;4-1;5-2;6-2;7-3;8-1;9-2;A-2;B-3;C-2;D-3;E-3;F-4) do (
for /F "tokens=1,2 delims=-" %%b in ("%%a") do (
set "onesIn[%%b]=%%c"
)
)
set ones=0
set "hex=%~2"
:hexCountLoop
set /A ones+=onesIn[%hex:~0,1%]
set "hex=%hex:~1%"
if defined hex goto hexCountLoop
endlocal & set "%1=%ones%"
exit /B
Convert the number to decimal and do the basic math: divide by 2 and sum the remainders.
Do it in chunks of 7 hexadecimal digits because batch file calculations support only 31 bits (2^31-1 or 2147483647 or 0x7FFFFFFF).
set hex=ABCDEFABCDEFABCDEF
set ones=0
:loopchunks
set /a decimal=0x%hex:~0,7%
set hex=%hex:~7%
:loopdigits
set /a ones+=decimal %% 2, decimal/=2
if not %decimal%==0 goto loopdigits
if defined hex goto loopchunks
echo %ones%
Output:
51
#ECHO OFF
SETLOCAL
FOR %%a IN (F37ABD abcdef 123 321 99 100 f11f 0 cafe) DO CALL :mainproc %%a
GOTO :eof
:mainproc
SET hexnum=%1
SET /a count1=0
:loop
SET /a hex1=0x%hexnum:~0,1%
:bitloop
SET /a count1+=%hex1% %% 2
SET /a hex1/=2
IF %hex1% gtr 0 GOTO bitloop
SET hexnum=%hexnum:~1%
IF DEFINED hexnum GOTO loop
ECHO %count1% 1s detected IN %1
GOTO :EOF
The for loop simply assigns the values in the list to the variable %%a in turn and executes the main part of the procedure with a parameter (%1) of that item.
Within the main procedure, initialise hexnum as the number to be analysed and count1 with the accumulated number of 1s
Then set hex1 to 0xstrung before (copy the first digit of hexnum) which will be a hex numeric, 0x0 to 0xf. SInce this is the format for cmd to accept a hex number, it sets hex1 to decimal 0..15
next add (hex1 mod 2) to count, that is 1 or zero if odd/even
next halve hex1. Since cmd calculates in integer mode, the result is truncated, hence 6=>3 and 7+>3
the result is >0, do the next binary digit. repeat until 0.
Toss out the first character of hexnum (assign the substring starting at character 1, given that it starts counting at "character 0")
If hexnum has characters left, repeat for the next hex digit
otherwise, report.
result:
17 1s detected IN F37ABD
17 1s detected IN abcdef
4 1s detected IN 123
4 1s detected IN 321
4 1s detected IN 99
1 1s detected IN 100
10 1s detected IN f11f
0 1s detected IN 0
11 1s detected IN cafe

Batch: count the number of digits in a variable

I want to find a way to know the number of digits in variable. For now, I'm trying to use this code. In this example, %var% is the variable that I need to know the number of digits it has.
set x=1
set var=12345
:LOOP
set temp=%var:~0,%x%%
if %temp%==%var% goto END
set x=%x%+1
goto LOOP
:END
Theoretically, at the end of the code %x% would be the number of digits %var% has. However, it doesn't work. I found out the problem is at the 3rd line. I modified the code to diagnose:
set x=1
set var=12345
:LOOP
set temp=%var:~0,%x%%
echo %temp%
pause
if %temp%==%var% goto END
set x=%x%+1
goto LOOP
:END
The result echoed was:
x%%
Can anyone pinpoint my mistake or give an alternative solution to determine the number of digits in a variable?
Here's a short solution, that only works for numeric variables:
set /a Log=1%var:~1%-%var:~1% -0
set /a Len=%Log:0=+1%
The variable %Len% will contain the number of digits in %var%.
Explanation
The basic idea is to convert the first digit to 1, and the rest of them (the 'trailing' digits) to 0's. Then we can use the string replacement function to replace all the 0's with +1 giving us 1+1+1.... and evaluate the string as an arithmetic expression. This will give us the total number of digits.
The 'trailing' digits can be gotten using %var:~1% and we convert them to 0 by subtracting them from the variable itself: 45678 - 5678 gives 40000 etc. However, the above code subtracts them from 1%var:~1% instead, in order to replace the first digit with 1 (i.e. 1 followed by the 'trailing' digits).
The reason for the extra -0 is in case %var% only has one digit, for example 7. In that case, the expression 1%var:~1%-%var:~1% would evaluate to 1- and the shell would complain: Missing operand. The -0 ensures that we always have a valid expression.
Now that we've converted the variable in to the proper form into %Log%, we can replace every occurrence of 0 with +1using %Log:0=+1% and evaluate the resulting expression using set /a, giving us our final result.
The main problem with your code is
set temp=%var:~0,%x%%
This does not work. The parser is not able to properly determine what percent sign belongs to what variable. You can enable delayed expansion and write it as
set "temp=!var:~0,%x%!"
For alternative versions, to handle any length string, any of the posted answers will work.
For a simpler solution, if you are sure the string is under 10 characters, then this is an alternative
set "x=0123456789%var%"
set "x=%x:~-10,1%"
As there is no build in function for string length, you can write your own function.
#echo off
setlocal
set "myString=abcdef!%%^^()^!"
call :strlen result myString
echo %result%
goto :eof
:strlen <resultVar> <stringVar>
(
setlocal EnableDelayedExpansion
set "s=!%~2!#"
set "len=0"
for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if "!s:~%%P,1!" NEQ "" (
set /a "len+=%%P"
set "s=!s:~%%P!"
)
)
)
(
endlocal
set "%~1=%len%"
exit /b
)
This function needs always 13 loops, instead of a simple strlen function which needs strlen-loops.
It handles all characters.
Source: How do you get the string length in a batch file?
Your are trying to do this loop :
#Echo Off
Set /P VrStr=Enter your string :
:Loop
If "%VrStr%" EQU "" Goto EndLoop
Set VrStr=%VrStr:~0,-1%
Set /A VrLgr+=1
Goto Loop
:EndLoop
Echo Number of char: %VrLgr%
Pause
You can use this to :
#echo off
setlocal EnableDelayedExpansion
Set /P $Tstring=Enter your string:
for /l %%a in (0,1,9000) do (set $t=!$Tstring:~%%a,1!&if not defined $t (echo [NB OF CHAR =] %%a&pause&exit /b))
pause

Floating point division in a batch file

I need to do a floating-point division in a dos batch.
I didn't find a way to do it. Something like this :
SET /A Res=10/3
returns a integer number.
Is it possible to do it ?
I know this is a very old topic, but I can't found a simple Batch method in all previous answers, so I post here a pure Batch solution that is very simple to use.
Perform operations using fixed point arithmetic in Batch is simple. "Fixed point" means that you must set a number of decimals in advance and keep it throughout the operations. Add and subtract operations between two Fixed Point numbers are performed directly. Multiply and division operations requires an auxiliary variable, that we can call "one", with the value of 1 with the right number of decimals (as "0" digits). After multiply, divide the product by "one"; before division, multiply the dividend by "one". Here it is:
#echo off
setlocal EnableDelayedExpansion
set decimals=2
set /A one=1, decimalsP1=decimals+1
for /L %%i in (1,1,%decimals%) do set "one=!one!0"
:getNumber
set /P "numA=Enter a number with %decimals% decimals: "
if "!numA:~-%decimalsP1%,1!" equ "." goto numOK
echo The number must have a point and %decimals% decimals
goto getNumber
:numOK
set numB=2.54
set "fpA=%numA:.=%"
set "fpB=%numB:.=%"
set /A add=fpA+fpB, sub=fpA-fpB, mul=fpA*fpB/one, div=fpA*one/fpB
echo %numA% + %numB% = !add:~0,-%decimals%!.!add:~-%decimals%!
echo %numA% - %numB% = !sub:~0,-%decimals%!.!sub:~-%decimals%!
echo %numA% * %numB% = !mul:~0,-%decimals%!.!mul:~-%decimals%!
echo %numA% / %numB% = !div:~0,-%decimals%!.!div:~-%decimals%!
For example:
Enter a number with 2 decimals: 3.76
3.76 + 2.54 = 6.30
3.76 - 2.54 = 1.22
3.76 * 2.54 = 9.55
3.76 / 2.54 = 1.48
Batch files as such do not support the floating point arithmetic. However, this article suggests a workaround that uses an external script file to do calculations. The script file should use some sort of eval function to evaluate the expression passed as an argument and return the result. Here's a sample VBScript file (eval.vbs) that does this:
WScript.Echo Eval(WScript.Arguments(0))
You can call this external script from your batch file, specify the expression to be evaluated and get the result back. For example:
#echo off
for /f %%n in ('cscript //nologo eval.vbs "10/3"') do (
set res=%%n
)
echo %res%
Of course, you'll get the result as a string, but it's better than nothing anyway, and you can pass the obtained result to the eval script as part of another expression.
According to this reference, there is no floating point type in DOS batch language:
Although variables do exist in the DOS batch programming language, they are extremely limited. There are no integer, pointer or floating point variable types, only strings.
I think what you are trying to do will be impossible without implementing your own division scheme to calculate the remainder explicitly.
I recently came across this batch file to compute an approximation of Pi.
There is a DivideByInteger label that might be useful to you: Stupid-Coding-Tricks-A-Batch-of-Pi
It uses a set of MaxQuadIndex variables, each containing a four-digit number (quadruple), in order to store the entire result. The code allows division by an integer between 1 and 10000, inclusive.
:DivideByInteger
if defined PiDebug echo.DivideByInteger %1 %2
set /a DBI_Carry = 0
for /L %%i in (!MaxQuadIndex!, -1, 0) do (
set /a DBI_Digit = DBI_Carry*10000 + %1_%%i
set /a DBI_Carry = DBI_Digit %% %2
set /a %1_%%i = DBI_Digit / %2
)
goto :EOF
A Print label is also available…
try this
SETLOCAL EnableExtensions EnableDelayedExpansion
call :calc_ 1 (99-(100*5/100^)^)
echo !calc_v!
goto :EOF
:calc_
set scale_=1
set calc_v=
for /l %%i in (1,1,%1) do set /a scale_*=10
set /a "calc_v=!scale_!*%2"
set /a calc_v1=!calc_v!/!scale_!
set /a calc_v2=!calc_v!-!calc_v1!*!scale_!
set calc_v=!calc_v1!.!calc_v2!
goto :EOF
just change
call :calc_ decimalpoint equataion
in the example
decimalpoint is 1
equataion is (99-(100*5/100^)^) ;make sure if you use () that you insert ^ before ) as in ^)
the answer is 94.0
if decimalpoint is 2
and equataion is 22/7 ;π pi
the answer is 3.14
I wrote a pure batch file specifically to do division. It takes the first number you input, and then divides it by the second one, and displays the result with as many decimal points as you specify.
Echo off
cls
if NOT "%3" == "" (
set n1=%1
set n2=%2
set max=%3
goto :begin
)
set counter=2
set n1=1
set n2=1
set ans=
:start
Echo.
Echo. 1 / 2
Echo.
Set /p N1= 1?
set /p N2= 2?
Set /p Max= Out how many Decimal Points?
:begin
set /a TmpAns=%N1%/%N2%
set ans=%TmpAns%.
:: Echo.%ans%.>Answer.txt
<nul set /p "=%Tmpans%."
set /a TmpSub=%N2%*%TmpAns%
set /a N1=%N1%-%TmpSub%
set N1=%N1%0
If NOT "%n1%" == "00" (
if %n1% LSS %N2% (
set N1=%N1%0
set ans=%ans%0
)
) else (
Goto :Finished
)
set count=0
:loop
If "%count%" == "%max%" (
Goto :Finished
)
set /a TmpAns=%N1%/%N2%
set ans=%ans%%TmpAns%
<nul set /p "=%Tmpans%"
set /a TmpSub=%N2%*%TmpAns%
set /a N1=%N1%-%TmpSub%
set N1=%N1%0
If NOT "%n1%" == "00" (
if %n1% LSS %N2% (
set N1=%N1%0
set ans=%ans%0
)
) else (
Goto :Finished
)
set /a count=%count%+1
goto :loop
:finished
cls
Echo.
Echo.
Echo.The Number
Echo.%ans%
Echo.
Echo.
set n1=1
set n2=1
pause
goto :eof
:eof
The answer put into the variable %Ans%. It can also be called with parameters. ("Divide.bat 50 27 5" would give you 50/27 out 5 decimal points.)
Since nowadays PowerShell is present on almost all machines, I would let PowerShell do the math and return the result to the batch.
Example:
set divident=10
set divisor=3
for /f "delims=" %%a in ('powershell -Command %divident%/%divisor%') do set result=%%a
#echo %result%
Explanation:
Input variables: Use set variables to define divident and divisor.
Calling powershell and assign result to a batch variable: for /f "delims=" %%a in ('powershell -Command ...) do set result=%%a (you may also check here: How to put a single PowerShell output string into a cmd variable?)
Note the above code will only work with integer input variables.
To support floating point input variables, we need to send the variables as strings inside quotations ("%variable%") and convert the strings within PowerShell back to Double, otherwise batch would interpret the commas as delimiters and PowerShell could not interpret the numbers.
Example:
set divident=10,5
set divisor=3,4
for /f "delims=" %%a in ('powershell -Command [convert]::ToDouble^(\"%divident%\"^)
/[convert]::ToDouble^(\"%divisor%\"^)') do set result=%%a
#echo %result%
Explanation:
Note in PowerShell you would do this like [convert]::ToDouble("10,5")/[convert]::ToDouble("3,5"). However in batch we need to escape the quotes using backslash, and we also need to add a "^" sign before and after the quoted parts: [convert]::ToDouble^("%divident%"^)/[convert]::ToDouble^("%divisor%"^)
If you're running in a command shell on Windows (rather than DOS), you can use VBScript to evaluate complex expressions including floating point math for you.
I have written a small helper library you can call to do this.
EvalBat Library on GitHub

Resources