# Calculation

Batch scripts can do simple 32-bit integer arithmetic and bitwise manipulation using SET /a command. The largest supported integer is 2147483647 = 2 ^ 31 - 1. The smallest supported integer is -2147483648 = - (2 ^ 31), assignable with the trick of `set /a num=-2147483647-1`

. The syntax is reminiscent of the C language.

Arithmetic operators include *, /, % (modulo), +, -. In a batch, modulo has to be entered as "%%".

Bitwise operators interpret the number as a sequence of 32 binary digits. These are ~ (complement), & (and), | (or), ^ (xor), << (left shift), >> (right shift).

A logical operator of negation is !: it turns zero into one and non-zero into zero.

A combination operator is ,: it allows more calculations in one set command.

Combined assignment operators are modeled on "+=", which, in "a+=b", means "a=a+b". Thus, "a-=b" means "a=a-b". Similarly for *=, /=, %=, &=, ^=, |=, <<=, and >>=.

The precedence order of supported operators, is as follows:

`( )`

`* / % + -`

`<< >>`

`&`

`^`

`|`

`= *= /= %= += -= &= ^= |= <<= >>=`

`,`

Literals can be entered as decimal (1234), hexadecimal (0xffff, leading 0x), and octal (0777, leading 0).

The internal bit representation of negative numbers is two's complement. This provides a connection between arithmetic operations and bit operations. For instance, -2147483648 is represented as 0x80000000, and therefore set /a num=~(-2147483647-1) yields 2147483647, which equals 0x7FFFFFFF (type set /a num=0x7FFFFFFF to check).

As some of the operators have special meaning for the command interpreter, an expression using them needs to be enclosed in quotation marks, such as this:

`set /a num="255^127"`

`set /a "num=255^127"`

- Alternative placement of quotation marks.

`set /a num=255^^127`

- Escape ^ using ^ instead of quotation marks.

Examples:

`set n1=40 & set n2=25`

`set /a n3=%n1%+%n2%`

- Uses the standard percent notation for variable expansion.

`set n1=40 & set n2=25`

`set /a n3=n1+n2`

- Avoids the percent notation around variable names as unneeded for /a.

`set /a num="255^127"`

- Encloses "^" in quotation marks to prevent its special meaning for the command interpreter.

`set /a n1 = (10 + 5)/5`

- The spaces around = do not matter with /a. However, getting used to it lends itself to writing "set var = value" without /a, which sets the value of "var " rather than "var".

`if 1==1 (set /a n1=(2+4)*5)`

- Does not work: the arithmetic brackets within grouping brackets cause trouble.

`if 1==1 (set /a n1=^(2+4^)*5)`

- Escaping the arithmetic brackets with caret (^) works, as does enclosing "n1=2+(4*5)" in quotation marks.

`set /a n1=2+3,n2=4*7`

- Performs two calculations.

`set /a n1=n2=2`

- Has the same effect as n1=2,n2=2.

`set n1=40 & set n2=25 & set /a n3=n1+n2`

- Works as expected.

`set /a n1=2,n2=3,n3=n1+n2`

- Works as expected.

`set n1=40 & set n2=25 & set /a n3=%n1%+%n2%`

- Does not work unless n1 and n2 were set previously. The variable specifications %n1%" and "%n2"% get expanded the first set command is executed. Dropping percent notation makes it work.
before

- Does not work unless n1 and n2 were set previously. The variable specifications %n1%" and "%n2"% get expanded the first set command is executed. Dropping percent notation makes it work.
`set /a n1=2,n2=3,n3=%n1%+%n2%`

- Does not work unless n1 and n2 were set previously, for the reason stated in the previous example.

`set /a n1=0xffff`

- Sets n1 using hexadecimal notation.

`set /a n1=0777`

- Sets n1 using octal notation.

`set /a n1=%random%`

- A pseudo-random number from 0 to 32767 = 2^15-1.

`set /a n1="%random%>>10"`

- A pseudo-random number from 0 to 31 = 2^5-1. The shift right operator drops 10 out of 15 bits, keeping 5 bits.

`set /a n1=%random%%50`

- A pseudo-random number from 0 to 49. Uses the % modulo operator. In a batch, %% is needed for modulo:
`set /a n1=%random%%%50`

. Because of this particular use of the modulo, the result is not perfectly uniform; it is uniform if the 2nd modulo operand--above 50--equals to a power of 2, e.g. 256 = 2^8.

- A pseudo-random number from 0 to 49. Uses the % modulo operator. In a batch, %% is needed for modulo:
`set /a n1="(%random%<<15)+%random%"`

- A pseudo-random number from 0 to 1073741823 = 2^30 - 1. Combines the two 15-bit random numbers produced by %random% alone to produce a single 30-bit random number..

`set /a n1="((%random%<<15)+%random%)%1000000"`

- As above, but again using modulo, this time to achieve the range 0 to 999999.

An example calculation that prints prime numbers:

@echo off setlocal set n=1 :print_primes_loop set /a n=n+1 set cand_divisor=1 :print_primes_loop2 set /a cand_divisor=cand_divisor+1 set /a cand_divisor_squared=cand_divisor*cand_divisor if %cand_divisor_squared% gtr %n% echo Prime %n% & goto :print_primes_loop set /a modulo=n%%cand_divisor if %modulo% equ 0 goto :print_primes_loop & REM Not a prime goto :print_primes_loop2

Links: