Page 1 of 1

New behavior with SET /A?

Posted: 05 Oct 2012 17:35
by dbenham
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

Re: New behavior with SET /A?

Posted: 05 Oct 2012 19:07
by Liviu
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

Re: New behavior with SET /A?

Posted: 05 Oct 2012 22:36
by dbenham
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

Re: New behavior with SET /A?

Posted: 06 Oct 2012 00:42
by Liviu
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

Re: New behavior with SET /A?

Posted: 08 Oct 2012 09:11
by walid2mi
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

Re: New behavior with SET /A?

Posted: 27 Oct 2012 01:04
by Aacini
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

Re: New behavior with SET /A?

Posted: 27 Oct 2012 08:13
by dbenham
@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