sum numbers in for loop, batch file - batch-file

I need to make a for loop that sums up numbers from 1 to x where x is users input number.
I know how to make the for loop and display those numbers but I don't know how to sum them at the same time.
FOR /L %%x IN (1,1,%x%) DO ( echo %%x
)

to do arithmetics, use set /a. Also use delayed expansion to use the variable inside a block (between ( and ))
setlocal enabledelayedexpansion
set sum=0
FOR /L %%x IN (1,1,%x%) DO (
set /a sum=!sum!+%%x
echo + %%x = !sum!
)

Related

How to find and replace a number in a file and increment it?

I have 5000 same files and I need to update numeric value in its content and increment it. Below is the batch script I use to find and replace a number in a certain file called BULK_1.txt.
I am not sure on how to increment the value after running search and replace.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set search=01118596270001
set replace=01118596270002
set "textFile=BULK_1.txt"
set "rootDir=C:\Batch"
for %%j in ("%rootDir%\%textFile%") do (
for /f "delims=" %%i in ('type "%%~j" ^& break ^> "%%~j"') do (
set "line=%%i"
setlocal EnableDelayedExpansion
set "line=!line:%search%=%replace%!"
>>"%%~j" echo(!line!
endlocal
)
)
endlocal
The result should be like below. The last 4 digits should be updated from 0001 to 5000 for each file
Content of the BULK_1.txt:
DMAIN Test_data 01118596270001
DDOC_DATA Test_docdata 01118596270001
Content of the BULK_2:
DMAIN Test_data 01118596270002
DDOC_DATA Test_docdata 01118596270002
Content of the BULK_3:
DMAIN Test_data 01118596270003
DDOC_DATA Test_docdata 01118596270003
According to your requirements you may need:
#echo off
setlocal EnableDelayedExpansion
for /L %%A IN (1 1 5000) do (
set num_processed=%%A
call:find_len num_processed
if !len! EQU 1 (set num_%%A=0111859627000%%A)
if !len! EQU 2 (set num_%%A=011185962700%%A)
if !len! EQU 3 (set num_%%A=01118596270%%A)
if !len! EQU 4 (set num_%%A=0111859627%%A)
)
for /L %%A IN (1 1 5000) do (
for /L %%B IN (1 1 2) do (
if %%B EQU 1 (
echo DMAIN Test_data !num_%%A!>BULK_%%A.txt
) else (
echo DDOC_DATA Test_docdata !num_%%A!>>BULK_%%A.txt
)
)
)
:find_len
set "s=!%~1!#"
set "len=0"
for %%P in (4 2 1) do (
if "!s:~%%P,1!" NEQ "" (
set /a "len+=%%P"
set "s=!s:~%%P!"
)
)
My code uses the way that #jeb has suggested here slightly edited.
First, we make a loop to count from 1 to 5000.
We want to count the length of each of these numbers. calling the find_len subroutine does this.
If the string length of the variable is 1, then it must be 0001. The number in front is the same in all cases.
If the string length of the variable is 2, then it must be 0010. The number in front is the same in all cases.
If the string length of the variable is 3, then it must be 0100. The number in front is the same in all cases.
If the string length of the variable is 4, then it must be 1000. The number in front is the same in all cases.
Note: If we tried something similar to set /a 0000+1 the result would be 1. That is why all of these complicates!.
In all cases, the variable names will be num_numberCurrentlyProcessed.
Now another loop, actually the same as before. It will loop 5000 times and will create 5000 files in the format BULK_num.txt.
Inside this loop, another loop is required from 1 to 2, as each file must have 2 lines.
If we are in line 1, we echo the specific text specified by OP.
If we are in line 1, we echo again the specific text specified by OP.
"I have 5000 same files" - it's a lot faster to write them from scratch than to edit each of them:
#echo off
setlocal enabledelayedexpansion
set "Hdr=DMAIN Test_data 0111859627"
set "Dta=DDOC_DATA Test_docdata 0111859627"
for /l %%a in (1,1,5000) do (
set "num=0000%%a" REM prepend some zeros
set "num=!num:~-4!" REM take last four chars
>Bulk_%%a.txt (
echo %Hdr%!num!
echo %Dta%!num!
)
)

Problems with for loops in batch file

I am trying to create a for loop in batch with some calculation using modulus from 1-100 then return an average for the entire set of numbers. I want to print this average on the screen and to a file called output This is what i have but it doesn't seem to be working correctly. Any suggestions? Thank you kindly.
#echo off
setlocal EnabledDelayedExpansion
for /l %%i in (1,1,100) do (
set /a EXPR = %%i %% 5
set /a EXPR2 = %EXPR+3
set /a TOTAL = TOTAL+%EXPR2
)
set /a AVG = %TOTAL/100
echo Your average is %AVG
echo Your average is %AVG >> output.txt
#echo off
setlocal EnableDelayedExpansion
for /l %%i in (1,1,100) do (
set /a EXPR=%%i %% 5
set /a EXPR2=EXPR+3
set /a TOTAL=TOTAL+EXPR2
)
set /a AVG=TOTAL/100
echo Your average is %AVG%
echo Your average is %AVG%
Is this what you want?
One additional d in EnableDelayedExpansion (btw. set /a works also without delayed expansion). Classical error is to let spaces surrounding variable assignment.In batch scripts result is that the space becomes part of the variable name.Except FOR tokens and command line arguments variables are two side enclosed with %

Squaring step variable - Batch for loop

Is it possible to square the increment/step variable in a batch for loop.
This is what it looks like right now
FOR /L %%A IN (1024,1000, 1048576) DO (
do stuff
)
however instead of going up by 1000 each time, I want to go up by 2^10, 2^11 .... 2^20 (1048576) is it possible to do that?
No, for /l loops can not handle geometric increments. But you can use batch arithmetics for it
for /l %%a in (10 1 20) do (
set /a "A=1<<%%a"
setlocal enabledelayedexpansion
for %%A in (!A!) do ( endlocal
rem Your code here - do stuff
echo %%A
)
)
Delayed expansion is needed to handle the changing variable inside the block of code. If your inner code has no problems with delayed expansion being active, it can be simplified as
setlocal enabledelayedexpansion
for /l %%a in (10 1 20) do (
set /a "A=1<<%%a"
rem Your code here - do stuff
echo !A!
)
If switching to PowerShell is fine for you, you can use
foreach ($i in 1..3) {
# example output
echo "1000^$i = $([Math]::Pow(1024, $i))"
# start "myprogram.bat --parameter $x
& 'myprogram.bat' #("--parameter", [Math]::Pow(1024, $i))
}

Batch - For Loop 1-100, mod 5 for each

Batch for a class...Can't figure this out. Currently have
:forLoop
echo.
for /L %%x in (1, 1, 100) do (
SET /A result=%%x %% 2
echo %%x
)
Any ideas guys?
Edit: I'm trying to use a for loop to iterate from 1 to 100. Then in the for loop obtain modulus of 1,2,3,4, etc. So in my example it would be modulus x. Where x is constantly incrementing.
Try this:
SETLOCAL ENABLEDELAYEDEXPANSION
:forLoop
echo.
for /L %%x in (1, 1, 100) do (
SET /A result=%%x %% 2
echo !result!
)
The first command is necessary for the variables to be expanded at execution time.
Delayed expansion (at run-time) of the variable is performed with the ! symbol.
If you use the %, you get the parse-time value.
EDIT:
Considering Stephan suggestion, i see that we can use call for a shorter solution:
for /L %%x in (1, 1, 100) do (
set /A result="%%x %% 2"
call echo %%result%%
)

How to find large factorials using a batch script

#echo off
if %1.==. ( echo Missing parameter! Try passing the number as a parameter like 'factorial 10' without the quotes.
goto end )
setlocal enabledelayedexpansion
set /a count=0
set /a temp=0
set /a digits=1
set /a array1=1
for /L %%i IN (2,1,%1) do (
set /a temp=0
for /L %%j IN ( 1,1,!digits! ) do (
set /a temp=!temp!+!array%%j!*%%i
set /a array%%j=!temp!%%10
set /a temp=!temp!/10 )
set /a index=!digits!+1
for /L %%v IN (!index!,1,!index! ) do (
if !temp! NEQ 0 (
set /a array!index!=!temp!%%10
set /a temp/=10
set /a index+=1 ))
set /a digits=!index!-1)
for /l %%v IN ( !digits!,-1,1 ) do set array=!array!!array%%v!
echo !array!
echo Total # of decimal digits = !digits!
:end
pause
This is what i have gotten so far. It is quite stable under 10! but once i reach 15 or 20 it starts missing out a few digits.
My edit....
#echo off
if %1.==. ( echo Missing parameter! Try passing the number as a parameter like 'factorial 10' without the quotes.
goto end )
setlocal enabledelayedexpansion
set /a count=0
set /a temp=0
set /a digits=1
set /a array1=1
for /L %%i IN (2,1,%1) do (
set /a temp=0
for /L %%j IN ( 1,1,!digits! ) do (
set /a temp=!temp!+!array%%j!*%%i
set /a array%%j=!temp!%%10
set /a temp=!temp!/10 )
for /l %%v IN ( 1,1,30 ) do (
if !temp! neq 0 (
set /a digits+=1
set /a array!digits!=!temp!%%10
set /a temp=!temp!/10
)))
for /l %%v IN ( !digits!,-1,1 ) do set array=!array!!array%%v!
echo !array!
echo Total # of decimal digits = !digits!
:end
pause
Now i am forcing the the last inner loop to run 30 times eventhough temp would have been zero way before that. Is there any way to write a snippet that would be analogous to the following c code
while (temp)
{/code goes here/}
This execute only as long as temp is non zero.
Is there any partyicular limit to how big a variable can be in a batch?
I know it is a pain * to debug computational programs in a batch, I'm just trying to code this in all programming languages i know, Just so i could compare their speeds. Can somebody Please point out what i'm doing wrong here.
edit........22/12/13
#echo off
if %1.==. ( echo Missing parameter! Try passing the number as a parameter like 'factorial 10' without the quotes.
goto end )
setlocal enabledelayedexpansion
set /a count=0
set /a tempo=0
set /a digits=1
set /a array1=1
for /f "tokens=1-4 delims=:.," %%a IN ("%time%") do (
set /a "start=(((%%a*60)+1%%b %% 100)*60+1%%c %%100)*100+1%%d %% 100"
)
for /L %%i IN (2,1,%1) do (
set /a tempo=0
for /L %%j IN ( 1,1,!digits! ) do (
set /a tempo=!tempo!+!array%%j!*%%i
set /a array%%j=!tempo!%%10000
set /a tempo=!tempo!/10000 )
for /l %%v IN (1,1,2) do (
if !tempo! neq 0 (
set /a digits+=1
set /a array!digits!=tempo%%10000
set /a tempo=tempo/10000
))
)
for /l %%v IN ( !digits!,-1,1 ) do set array=!array!!array%%v!
echo !array!
echo Total # of decimal digits = !digits!
for /f "tokens=1-4 delims=:.," %%a in ("%time%") do (
set /a "end=(((%%a*60)+1%%b %% 100)*60+1%%c %%100)*100+1%%d %% 100"
)
set /a elapsedcs=end-start
set /a elapseds=elapsedcs/100
set /a elapsedcs=elapsedcs%%100
echo %elapseds%.%elapsedcs% seconds
:end
rem label should never be the last statement
Is this what you meant aacini?
In order to achieve fast arithmetic operations on Big numbers in Batch, you must split the Bignum in groups of digits that can be managed via the 32-bits operations of set /A command. The maximum 32-bits signed integer is 2147483647, so the largest group of digits that can be multiplied this way is 4, because 5 digits (99999 x 99999) exceed the maximum number. Addition and multiplication must be achieved from right to left translating a "carry" to the next group to the left. Subtraction and division must be achieved from left to right translating a "borrow" to the next group to the right. The Batch file below use this method to succesively multiply a Bignum by a 4 digits factor, so it can calculate up to 9999! as long as all variables that contain the groups of 4 digits fits in the 64 MB size limit of the environment (look for "65,536KB maximum size" under "Setting environment variables"). The result is directly output to the screen in order to avoid the 8192 digits limit of one Batch variable.
EDIT: I slightly modified the program in order to run faster and get the number of digits in the result.
#echo off
if "%1" equ "" (
echo Missing parameter! Try passing the number as a parameter like 'factorial 10' without the quotes.
goto end
)
setlocal EnableDelayedExpansion
rem Calculate the factorial
set /A g1=1, groups=1
for /L %%n in (2,1,%1) do (
set carry=0
for /L %%g in (1,1,!groups!) do (
set /A group=g%%g*%%n+carry, g%%g=group%%10000, carry=group/10000
)
if !carry! neq 0 (
set /A groups+=1
set g!groups!=!carry!
)
)
rem Show the factorial
set /P "=!g%groups%!" < NUL
set /A groupsM1=groups-1
for /L %%g in (%groupsM1%,-1,1) do (
set group=000!g%%g!
set /P "=!group:~-4!" < NUL
)
echo/
rem Get the number of digits
set digits=0
for /L %%i in (0,1,3) do if "!g%groups%:~%%i,1!" neq "" set /A digits+=1
set /A digits+=4*groupsM1
echo Total # of decimal digits = %digits%
:end
pause
I had to rereread the code to see what it is doing. Nice.
You have to face three limits on your code.
1 - In the inner %%j and %%v loop, where buffer is used to multiply the current value in %%i, you face the limit indicated by Magoo. You can not operate with set /a with values greater than 2^31. As the values in the array are limited to 0-9, this means that this limit will not let you calculate factorials of numbers greater than 214748364 (aprox)
2 - There is a limit in the size of a environment variable. It can not hold more than 32767 characters. As you are concatenating the digits to output to console (the next limit is related), this limits you to factorials of numbers below 9273 (aprox).
3 - There is a limit in the length of the lines cmd can handle. It is 8191 characters. This does not limit your calc, but you can not use the method of concatenating in a variable to represent the number. If the method is not changed, this limits you to factorials of numbers below 2727 (aprox).
Batch is limited to signed-32-bit integers.
BTW - don't use temp or tmp as a user-variable. It is set by the system as a pointer to a directory where temporary files are stored.

Resources