npocmaka

Just compared the SET /? and SS64 page.

Nothing is mentioned about : ~ , ! (and in fact also for - as a unary operator) and , .As they are almost obvious the parentheses also are not mentioned as logical separators ..

~ is the most strange - It acts as -(x+1) :

Code: Select all

```
C:\>set /a "i=~5"
-6
C:\>set /a "i=~(-5)"
4
```

! is the most useless -In fact I don't know if it can do anything at all - it acts as every non-arithmetic symbol and used as a unary operator converts anything to 0 :

Code: Select all

```
C:\>set /a "i=s7"
0
C:\>set /a "i=!7"
0
```

! can be used against zero.And help about << and >> seems to be not correct (check the example).

I have no idea why it's included in the help (I still hope for some uber-super-duper hidden feature).

, is the most fun (I have definitions for all of them ) .With this a few arithmetic variables could be initialized or an arithmetic operation could be executed without being assigned to a variable:

Code: Select all

```
C:\>set /a "i=1,5+3"
8
C:\>set /a "i=1,2+2"
4
C:\>set /a "i=1,2+2,j=3+2"
5
C:\>echo %i% and %j%
1 and 5
C:\>set /a "2+2"
4
```

Code: Select all

```
C:\>set /a "i=1,(2,+23)+2"
25
```

----------------------------

#2 16 Jan 2013 02:57

npocmaka

And three more pitfalls of set /a :

Code: Select all

```
C:\>set /a "a=1,b=1+%a%"
Missing operand.
```

Code: Select all

```
@echo off
setlocal ENABLEDELAYEDEXPANSION
set /a "a=1,b=1+!a!"
echo !b!
endlocal
```

here b will be 0 :

Code: Select all

```
@echo off
setlocal ENABLEDELAYEDEXPANSION
set /a "a=0"
set /a "b=!!a!"
echo !b!
endlocal
```

Code: Select all

```
@echo off
setlocal
set /a "a=5"
call set /a "b=6^%a%"
call set /a "b=6%%a%"
endlocal
```

#3 16 Jan 2013 05:58

carlos

npocmaka. I write that I learn in my experience with this command. The /A in set maybe means arithmetic, and means that the expression will be evaluated. Then:

Code: Select all

`set "n=5"`

Code: Select all

`set /a "n=5"`

The ! (logical negation), for work with it is neccesary turn off delayed expansion. 0 is turned 1 and all other is turned 0.

The ~ (bitwise negation) is complement.

The - (sign negation) positive sign turn negative, and negative sign turn positive.

With extensions enabled you can use the other expansion:

Is not necessary turn on delayedexpansion.

You only use the name of the variable:

Code: Select all

```
Set "number=10"
Set /a "new=1+number"
```

----------------------------

#4 16 Jan 2013 08:05

npocmaka

this was unexpected but cool ...carlos wrote:

Code: Select all

`Set "number=10" Set /a "new=1+number"`

Turns out that consecutive sets work after all:

Code: Select all

```
C:\>set /a "first=1,second=first+1"
2
```

Last edited by npocmaka (16 Jan 2013 11:42)

----------------------------

#5 16 Jan 2013 12:14

carlos

This is a example of use of ! operator:

Code: Select all

```
@Echo Off
SetLocal Enableextensions
Call :isLeap 2008
Echo 2008 : leap : %errorlevel%
Call :isLeap 2000
Echo 2000 : leap : %errorlevel%
Call :isLeap 1900
Echo 1999 : leap : %errorlevel%
Pause
Goto :Eof
:isLeap
::Author: Carlos
::Return 0 or 1 if is leap year
::Argument: year
SetLocal EnableExtensions DisableDelayedexpansion
Set /A "ly=(!(%~1%%4)&!!(%~1%%100))|!(%~1%%400)"
Exit /B %ly%
```

----------------------------

#6 16 Jan 2013 15:47

npocmaka

carlos wrote:

The ! (logical negation), for work with it is neccesary turn off delayed expansion. 0 is turned 1 and all other is turned 0.

Hmm.. Probably cmd.exe searches for a variable when expansion is on - and does not effect then.

More interesting SET /A does not work with DISABLEEXTENSIONS at all :carlos wrote:

With extensions enabled you can use the other expansion:

Code: Select all

```
@echo off
setlocal
setlocal ENABLEDELAYEDEXPANSION
set /a "test1=!0"
echo !test1!
set /a "test1=!1"
echo !test1!
endlocal
set /a "test2=!0"
echo %test2%
set /a "test2=!1"
echo %test2%
setlocal DISABLEEXTENSIONS
set /a "test5= 1 + 1"
rem will not display **2**
echo **%test5%**
endlocal
setlocal DISABLEEXTENSIONS
rem this produce error
set /a "test3=!0"
echo %test3%
set /a "test3=!1"
echo %test3%
endlocal
setlocal DISABLEEXTENSIONS ENABLEDELAYEDEXPANSION
rem this produce error too
set /a "test4=!0"
echo %test4%
set /a "test4=!1"
echo %test4%
endlocal
endlocal
```

----------------------------

#7 17 Jan 2013 02:17

Simon Sheppard

I've updated the SET page now, thanks for flagging this up npocmaka

----------------------------

#8 17 Jan 2013 03:20

Aacini

Comma operator allows to perform large calculations in just one line, like in this example:

Code: Select all

```
REM CALCULATE MONTH AND DAY OF THE EASTER SUNDAY OF THE GIVEN YEAR
SET YY=%1
SET /A A=YY%%19, B=YY/100, C=YY%%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, K=C%%4, L=((E+I)*2-H-K+32)%%7, M=(A+H*11+L*22)/451, N=H+L-M*7+114, MM=N/31, DD=N%%31+1
ECHO Easter Sunday of year %YY% is on month %MM% day %DD%
```

Code: Select all

`SET /A D=(B=YY/100)/4, E=B%%4, G=(B-(B+8)/25+1)/3, H=((A=YY%%19)*19+B-D-G+15)%%30, K=(C=YY%%100)%%4, M=(A+H*11+(L=((E+C/4)*2-H-K+32)%%7)*22)/451, MM=(N=H+L-M*7+114)/31, DD=N%%31+1`

Code: Select all

```
rem Copy N random numeric elements from Original to New vectors
for /L %%i in (1,1,%N%) do (
set /A index=(!random!*upperLimit)/32768+1
set /A New[!index!]=Original[!index!]
)
```

Code: Select all

```
for /L %%i in (1,1,%N%) do (
set /A index=(!random!*upperLimit)/32768+1, New[!index!]=Original[!index!]
)
```

Exclamation-mark (logical NOT) operator is the key to achieve conditional expressions in a way equivalent to C's conditional operator (cond)?then:else, but just for certain particular cases. For example, next line check if SIZE variable value is in range from LEFT to RIGHT (emulating an AND operation):It is interesting to note that in the evaluation of previous equation, the substitution of variable values are performed three times in the same line:Code: Select all

`rem DRAWEQUATION.BAT - Draw simple equations y=f(x) in X-Y plane for /L %%x in (0,1,%maxCol%) do ( set /A "y=(Top-(%f(x)%))/yStep" . . . . )`

0- Read the equation: f(x)=SIN[!x!]*20>>16

1- Normal %variable% expansion: set /A "y=%f(x)%" becomes: set /A "y=SIN[!x!]*20>>16"

2- Delayed !variable! expansion: set /A "y=SIN[!x!]*20>>16" becomes: set /A "y=SIN[1]*20>>16" (when x=1)

3- Replace variable values in SET /A command: set /A "y=1144*20>>16"

Code: Select all

```
set /A "C1=1,A=left-size,C1=!((A+1)/A), C2=1,A=size-right,C2=!((A+1)/A), test=C1*C2"
if %test% equ 1 (
echo Size variable is in range
) else (
echo Size variable out of range
)
```

Although SET /A documentation indicate that >> operator is right "logical shift" (RSH), it really operate as right "arithmetic shift" (RAS). If you need a pure logical shift, you must cancel the sign bit after the shift:

Code: Select all

```
C:>set /A var=-1
-1
C:>set /A "ras=var>>1"
-1
C:>set /A "rsh=var>>1&~(1<<31)"
2147483647
```

Antonio

----------------------------

#9 28 Oct 2013 17:21

npocmaka

set /a outputs it result without new line at the end ? yikes

Code: Select all

```
C:\>set /a 1 & set /a 2
12
C:\>
```

#10 30 Oct 2013 22:56

carlos

very interesting. that occurs in the interactive mode, almost in windows xp.npocmaka wrote:

Code: Select all

`set /a outputs it result without new line at the end ? yikes C:\>set /a 1 & set /a 2 12 C:\>`

----------------------------

#11 03 Mar 2015 07:20

jumper

another handy feature is that it lets you assign multiple variables at once:

Code: Select all

`set /a a=b=c=d=10`