New behavior with SET /A?

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

New behavior with SET /A?

#1 Post by dbenham » 05 Oct 2012 17:35

I just discovered some SET /A behavior that is new for me. (assume all variables are cleared before each example)

1) Extra spaces are ignored in both the name and the value. This one does not surprise me much.

Normally, extra spaces in a SET statement are incorporated into the name and/or value.

Code: Select all

C:\test>set var1   =    33

C:\test>set var1
var1   =    33

But extra spaces in SET /A are ignored

Code: Select all

C:\test>set /a var1   =    33
33
C:\test>set var1
var1=33


2) A single computation can perform multiple assignments if parentheses are used. This one is a very pleasant surprise :D

Code: Select all

C:\test>set /a var1=33
33
C:\test>set var2=

C:\test>set var
var1=33

C:\test>set /a var1+=(var2=10)
43
C:\test>set var
var1=43
var2=10


Dave Benham

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: New behavior with SET /A?

#2 Post by Liviu » 05 Oct 2012 19:07

dbenham wrote:2) A single computation can perform multiple assignments if parentheses are used. This one is a very pleasant surprise :D

Neat! And now, for the obligatory abuse of such surprise, the following appears to work as an 8th power shorthand ;-)

Code: Select all

@echo off &setlocal enableDelayedExpansion
set /a v1=2
set /a v1*=(v1*=(v1*=v1)) & echo %v1%*=(%v1%*=(%v1%*=%v1%)) == !v1!

Code: Select all

2*=(2*=(2*=2)) == 256

On a more serious note, it does indeed appear that the order of evaluation is inner paranthesis first, and left to right among peers.

Code: Select all

set /a v1=2
set /a v1*=(v1+=1)*(v1+=3) & echo %v1%*=(%v1%+=1)*(%v1%+=3) == !v1!

Code: Select all

2*=(2+=1)*(2+=3) == 108
- with v1=2, v1+=1 sets v1 to 3;
- with v1=3, v1+=3 sets v1 to 6;
- with v1=6, v1*=3*6 gives 108.

Liviu

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: New behavior with SET /A?

#3 Post by dbenham » 05 Oct 2012 22:36

Very nice - those examples might give a few people a headache :wink:

Liviu wrote:On a more serious note, it does indeed appear that the order of evaluation is inner paranthesis first, and left to right among peers.

Yes - One of the rare cases where the HELP documentation does a good job. The order of precedence is well documented.

Code: Select all

C:\test>HELP SET
...
...  The expression evaluator is pretty simple and supports the following
operations, in decreasing order of precedence:

    ()                  - grouping
    ! ~ -               - unary operators
    * / %               - arithmetic operators
    + -                 - arithmetic operators
    << >>               - logical shift
    &                   - bitwise and
    ^                   - bitwise exclusive or
    |                   - bitwise or
    = *= /= %= += -=    - assignment
      &= ^= |= <<= >>=
    ,                   - expression separator
...


Dave Benham

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: New behavior with SET /A?

#4 Post by Liviu » 06 Oct 2012 00:42

dbenham wrote:One of the rare cases where the HELP documentation does a good job. The order of precedence is well documented.

Sorry, can't let that pass unchallenged ;-) yes, the precedence is well defined, but the "associativity and order of evaluation" is not. Turns out that, for math operators at least, it is indeed left to right (otherwise the result below wouldn't be 1333).

Code: Select all

set /a v1=0 & set /a v1+=(v1+=1)+(v1+=10)*(v1+=100) &echo !v1! &rem v1 == 1333

But, for example, the assignment operators (=, += etc) "associate" right to left.

Code: Select all

set /a w1  = w2  = 1 & echo w1 = !w1!, w2 = !w2! & rem w1 = 1, w2 = 1
set /a w1 += w2 += 1 & echo w1 = !w1!, w2 = !w2! & rem w1 = 3, w2 = 2
set /a w1 += w2  = 1 & echo w1 = !w1!, w2 = !w2! & rem w1 = 4, w2 = 1
set /a w1  = w2 += 1 & echo w1 = !w1!, w2 = !w2! & rem w1 = 2, w2 = 2

Liviu

walid2mi
Posts: 3
Joined: 01 Dec 2011 02:10
Contact:

Re: New behavior with SET /A?

#5 Post by walid2mi » 08 Oct 2012 09:11

hi,

you can also us this syntax for multi assignement:

Code: Select all

CMD I> set /A a=b=c=d=e=20


or for count words:

Code: Select all

CMD I> set W=sample test string hello world
CMD I> set/A X=1+%W: =,X+=1+%
5


or for using without enable delayed expansion

Code: Select all

CMD I> set T=10
          set S=20
          set /a N= T * S


or inject value in another var:

Code: Select all

CMD I>  set a=60,b=20
           for /f %%x in ('"set /a (a-b)/4"') do set c=%%x


...etc

sorry for my english

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: New behavior with SET /A?

#6 Post by Aacini » 27 Oct 2012 01:04

The expression separator operator (comma) allows to achieve multiple variable assignments with no parentheses:

Code: Select all

set /A one=1, two=2, three=3

Previous line execute faster than three separate SET or SET /A commands. Several comma operators in the same SET /A command are executed from left to right:

Code: Select all

set /A T=10, S=20, N= T * S
set /A a=60,b=20, c=(a-b)/4

This feature allows to write complex algebraic expressions in just one SET /A command that execute much faster than individual commands, for example:

Code: Select all

:EasterSunday year
rem Calculate the date of Christian Easter Sunday of any given year
rem Antonio Perez Ayala
set /A A=%1%%19, B=%1/100, C=%1%%100, D=B/4, E=B%%4, F=(B+8)/25, G=(B-F+1)/3, H=(A*19+B-D-G+15)%%30, I=C/4
set /A K=C%%4, L=((E+I)*2-H-K+32)%%7, M=(A+H*11+L*22)/451, N=H+L-M*7+114, Month=N/31, Day=N%%31+1
echo %Month%/%Day%/%1

Antonio

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: New behavior with SET /A?

#7 Post by dbenham » 27 Oct 2012 08:13

@Aacini. Sure, I've been doing that with commas for a long time. I was considering it a separate computation after the comma (yes, faster then individual SET /A commands, less typing as well).

But putting multiple assignments in one computation using parentheses (without commas) opens up some interesting possibilities, as Liviu has demonstrated. I had never tried it before and was surprised it worked.


Dave Benham

Post Reply