Page 1 of 1

Increment an integer without SET

Posted: 17 Oct 2013 04:43
by einstein1969
hi to all,

Does anyone know how to increment a variable that contains the representation of an integer?

I would suffice the increase of 1 or a few units

I would avoid the use of the SET (or the SET / A) and if possible use only one or two expansions (or if there is a chance even three). So that is faster than the use of the "SET".

I need to numbers ranging from 0 to 8191 (theoretical max for a environment variable for DOS BATCH)

Thanks

Einstein1969

Re: Increment an integer without SET

Posted: 17 Oct 2013 06:06
by jeb
I can't see the sense of avoiding set /a :?:

What is wrong with

Code: Select all

set /a myCounter=0
for /F %%L in (text.txt) DO (
  set /a myCounter+=1
)

Re: Increment an integer without SET

Posted: 17 Oct 2013 06:20
by ShadowThief
I'd be really curious to see how somebody could change the value of a variable without using SET.

Closest thing I can think would be

Code: Select all

for /L %%A in (0,1,8191) do (
    rem whatever you're doing with %%A
)

Re: Increment an integer without SET

Posted: 17 Oct 2013 08:28
by einstein1969
Ok. I have formuled the question wrong! You are right!

I use this code for change the content of string:

one_char_change:

Code: Select all

setlocal EnableDelayedExpansion

set s=0123456789
set Pos=4
set newvalue=#

set /a Pos2=Pos+1
set s=!s:~0,%Pos%!!newvalue!!s:~%Pos2%!

echo !s!

rem OR

set s=0123456789
set Pos=4
set newvalue=#

set last=!s:~%Pos%!
set s=!s:~0,%Pos%!!newvalue!!last:~1!

echo !s!


It is possibile cut the "set /a Pos2=Pos+1" or "set last=!s:~%Pos%!" and using one SET?

Einstein1969

Re: Increment an integer without SET

Posted: 17 Oct 2013 08:34
by einstein1969
jeb wrote:I can't see the sense of avoiding set /a :?:


For performance reason (if we can do it)

Re: Increment an integer without SET

Posted: 17 Oct 2013 08:43
by foxidrive
einstein1969 wrote:
jeb wrote:I can't see the sense of avoiding set /a :?:


For performance reason (if we can do it)


If you are looking for performance then why are you using batch?
Even an interpreted basic program will blow batch out of the water for speed.

Re: Increment an integer without SET

Posted: 17 Oct 2013 09:08
by einstein1969
foxidrive wrote:
einstein1969 wrote:
jeb wrote:I can't see the sense of avoiding set /a :?:


For performance reason (if we can do it)


If you are looking for performance then why are you using batch?
Even an interpreted basic program will blow batch out of the water for speed.


you are right!
I could certainly do the same thing in assembler or any other language or script interpreter etc.

But I'm delving into the batch dos.

Einstein1969

Re: Increment an integer without SET

Posted: 17 Oct 2013 13:28
by aGerman
SET is a CMD - internal command. That means it's as fast as a command can be. No idea why you are thinking it would cause a bad performance in your batch code. If you want to improve the peformance of a batch code the try to avoid external commands (at least try to avoid calling them several times for the same reason).

That code will separate the commands that are listed in HELP:

Code: Select all

@echo off &setlocal

set /a int=0, ext=0
for /f %%i in ('help^|findstr /rbc:"[A-Z][ABCDEFGHIJKLMNOPQRSTUVWXYZ]"') do (
  for /f "tokens=1,2 delims=?" %%j in ("%%i.exe?%%i.com") do (
    if "%%~$PATH:j%%~$PATH:k"=="" (
      call :out %%i
    ) else (
      set /a ext+=1
      echo %%i "%%~$PATH:j%%~$PATH:k"
    )
  )
)

echo(
echo internal %int%
echo external %ext%
pause>nul
goto :eof

:out
set /a int+=1
set "line=%1                                                  "
echo %line:~,50% - internal
goto :eof

Regards
aGerman

Re: Increment an integer without SET

Posted: 17 Oct 2013 15:21
by einstein1969
Thank you for the wise suggestion, but I'm using at the moment few external commands. I'll probably have to revise the logic to break down the problem of declining performance.

This script is phenomenal! :shock: It will take me a double cup of coffee to figure out how do you generate the list. :roll:

Anyway back to the problem of performance. I saw that SET is fast but sometimes it is slower than an expansion. So I thought that populate a variable upstream then use it would be good for performance. My goal is both qualitative (functional) and performance.

Einstein1969

Re: Increment an integer without SET

Posted: 17 Oct 2013 16:16
by aGerman
I'm using at the moment few external commands

You can't avoid it. What I actually meant is that you could use COPY instead of XCOPY if you simply have to copy a file. Or that you could apply FINDSTR to a file / a set of files instead of applying it to each line / each file separately.
The reason why it decreases the performance enormously is that Windows needs some time to load the process. Depending on RAM, number of CPUs, clocking, current CPU usage etc. it wastes approx. 200ms each time you call an external command.

It will take me a double cup of coffee to figure out how do you generate the list.

Actually it's very simple. I process the list of commands that the HELP command displays. I append .exe and .com to the commands and use the ~$path: modifier of FOR variables to check if such a file can be found in the PATH environment.

Regards
aGerman

Re: Increment an integer without SET

Posted: 17 Oct 2013 18:48
by einstein1969
aGerman wrote:
I'm using at the moment few external commands

You can't avoid it. What I actually meant is that you could use COPY instead of XCOPY if you simply have to copy a file. Or that you could apply FINDSTR to a file / a set of files instead of applying it to each line / each file separately.
The reason why it decreases the performance enormously is that Windows needs some time to load the process. Depending on RAM, number of CPUs, clocking, current CPU usage etc. it wastes approx. 200ms each time you call an external command.

It will take me a double cup of coffee to figure out how do you generate the list.

Actually it's very simple. I process the list of commands that the HELP command displays. I append .exe and .com to the commands and use the ~$path: modifier of FOR variables to check if such a file can be found in the PATH environment.

Regards
aGerman


Thanks for explain aGerman.

Yes, I can't avoid. But depend of nature of application. There are application that use 200ms for call external program and 20000ms of internal command. And if i reduce of 40% than i'm happy.

Meanwhile i have find a way.... difficult to follow

for value from 0 to 8 (I dread to think how to get to 8192)

result:

Code: Select all

Without SET /A
#123456789
##23456789
###3456789
####456789
#####56789
######6789
#######789
########89
#########9

With SET /A
#123456789
##23456789
###3456789
####456789
#####56789
######6789
#######789
########89
#########9


Code: Select all

@echo off & setlocal EnableDelayedExpansion

set newvalue=#

set pos2=1234567890

set s=0123456789

echo Without SET /A

For /L %%# in (0,1,8) do (
   rem set /a Pos2=Pos+1
   for %%A in ("!Pos2:~%%#,1!") do set s=!s:~0,%%#!!newvalue!!s:~%%~A!
   echo !s!
)

set s=0123456789
echo(
echo With SET /A

For /L %%# in (0,1,8) do (
   set /a Pos2=%%#+1
   for %%A in (!Pos2!) do set s=!s:~0,%%#!!newvalue!!s:~%%A!  <---can optimize this?
   echo !s!
)


Timing:

Code: Select all

   Environ       Grow   Change a string with:
      Size     Environ   SET/A +1    EXP_EQ.   GAIN
   ----------------------------------------------------
      4907       0.00       2.65       2.17     19%
     15451       0.01       3.98       2.89     28%
     36052       0.02       7.22       4.66     36%
     77252       0.06      15.68       9.74     38%
    159705       0.27      33.85      19.14     44%


How do I make the rest of the numbers?

Einstein1969

Re: Increment an integer without SET

Posted: 21 Oct 2013 19:24
by Aacini
Perhaps is this what you want?

Code: Select all

@echo off & setlocal EnableDelayedExpansion

for /L %%a in (0,1,9) do (
   set inc[!last!]=%%a
   set last=%%a
)

set newvalue=#

set s=0123456789

echo REALLY Without SET /A
For /L %%# in (0,1,8) do (
   for %%A in (!inc[%%#]!) do set s=!s:~0,%%#!!newvalue!!s:~%%A!
   echo !s!
)

Re: Increment an integer without SET

Posted: 21 Oct 2013 22:27
by carlos
More speedy:

Code: Select all

Echo #123456789
Echo ##23456789
Echo ###3456789
Echo ####456789
Echo #####56789
Echo ######6789
Echo #######789
Echo ########89
Echo #########9

Re: Increment an integer without SET

Posted: 22 Oct 2013 05:43
by einstein1969
@Aacini

Aacini wrote:Perhaps is this what you want?

Code: Select all

@echo off & setlocal EnableDelayedExpansion

for /L %%a in (0,1,9) do (
   set inc[!last!]=%%a
   set last=%%a
)

set newvalue=#

set s=0123456789

echo REALLY Without SET /A
For /L %%# in (0,1,8) do (
   for %%A in (!inc[%%#]!) do set s=!s:~0,%%#!!newvalue!!s:~%%A!
   echo !s!
)


Thanks Aacini , this work but I had already considered the use of "classic" vector . But for performance issues I'm trying to use as few variables as possible. Without going to the extreme dictated by carlos: D I found a solution by using a mechanism such as the "map and lookup" described on the site even though it is currently limited to much lower values ​​than 8192 which was my original goal.

However, for the moment, your solution is the best because overcomes the limitation of 8192

ingenious use of the "last" in your code 8)

my last code:

Code: Select all

@echo off & setlocal EnableDelayedExpansion

set newvalue=#

rem create like this ....20-20#21-21#22-22#23-23#24-24#25-25#26-26#27-27#28-28#29-....

set newpos2=
For /L %%# in (0,1,98) do (
   
   set /a ns=%%#+1
           set ns=0!ns!
   set n=0%%#
   set n=!n:~-2!#!ns:~-2!-
   set newpos2=!newpos2!!n!
       
)

rem echo !newpos2!

rem test

set s=0123456789abcdefghijklhmenopqrstuvwxyz

set pos=19
for /f "delims=-" %%t in ("!newpos2:*%pos%#=!") do set s=!s:~0,%pos%!!newvalue!!s:~%%t!
echo !s!



@carlos

nice :D

I'm seriously thinking that it is the best solution at the time. Just prepare before everything and then use it at the appropriate time. Brilliant!

But to get the result must always pass for processing ...

Use the best environment I think is one of my goals or even a presentiment that it is a path with no way out ...

Einstein1969

Re: Increment an integer without SET

Posted: 22 Oct 2013 10:43
by carlos
I think that the task can coded in many ways, But the best principle for programming is "Programming only that you need". The really task is print the number of sharp.
In this case, we have a union in that in row 1 we print 1 sharp, in row 2 we print 2 sharps.
In all the task we need index variables, but because you need not use a environment variable, we choose a for /l variable.
And also we have other option, use a counter for print 1 sharp, for example if we need print 3 asterisk do for /l %%# in (1,1,3) do print # or have a hardcoded variable for print %var:~1,3%

Then there are variants of programming.

This is a option:

Code: Select all

@Echo Off
SetLocal EnableDelayedExpansion

Set num=_123456789
Set rep=_#########
For /L %%R in (1,1,9) Do Echo !rep:~1,%%R!!num:~%%R!

Pause


and other variant:

Code: Select all

@Echo Off
SetLocal EnableDelayedExpansion

Set num=123456789
Set rep=#########
For /L %%R in (0,1,8) Do Echo #!rep:~0,%%R!!num:~%%R!

Pause