# Calculation

suggest change

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:

1. `( )`
2. `* / % + -`
3. `<< >>`
4. `&`
5. `^`
6. `|`
7. `= *= /= %= += -= &= ^= |= <<= >>=`
8. `,`

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

• `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.
• `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:

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:

Table Of Contents