Section
Windows
Updated
19 Aug 2026
Examples
26

PowerShell is rarely the tool you would pick to do mathematics. But once a script is already counting files, converting bytes into gigabytes, or averaging a column out of a CSV, shelling out to something else for the arithmetic costs more than learning the handful of operators and [Math] methods that cover the job.

TL;DR: $x = 3; $y = $x + 2; $y prints 5. There is no ** operator — exponentiation is [Math]::Pow(2, 3).

👉 Examples below were run on PowerShell 7.4.2. Anything using [Math] also works in Windows PowerShell 5.1, since both sit on the same .NET type.

Basic arithmetic operators

Addition, subtraction, multiplication, division and modulus use the operators you would expect:

powershell
$sum        = 10 + 20
$difference = 30 - 15
$product    = 5 * 3
$quotient   = 25 / 5
$remainder  = 7 % 3

Write-Host "Sum: $sum, Difference: $difference, Product: $product"
Write-Host "Quotient: $quotient, Remainder: $remainder"
text
Sum: 30, Difference: 15, Product: 15
Quotient: 5, Remainder: 1

++ and -- increment and decrement a variable by one, which is what you want for counters:

powershell
$count = 0
$count++
$count      # 1
$count--
$count      # 0

The compound assignment operators +=, -=, *=, /= and %= apply an operation to a variable in place:

powershell
$number = 5
$number += 10   # 15
$number -= 3    # 12
$number *= 2    # 24
$number /= 4    # 6
$number %= 3    # 0

There is no **=, for the same reason there is no **. See the exponent section below.

Hex literals and size multipliers

Two shorthands save a lot of typing in system administration scripts. Hexadecimal literals are written 0x… and behave like any other number, which is convenient when you are working from registry DWORDs or Windows error codes:

powershell
0x10 + 0x05    # 21

And KB, MB, GB, TB and PB are numeric multipliers built into the language, so you never have to write out a power of 1024:

powershell
1GB            # 1073741824
1GB / 1MB      # 1024

Division does not truncate

This is the part that catches people arriving from Bash. In Bash, $((10 / 4)) gives 2, because arithmetic expansion is integer-only. PowerShell widens the result to a Double instead:

powershell
(25 / 5).GetType().Name    # Int32
(10 / 4).GetType().Name    # Double
10 / 4                     # 2.5

A division that comes out even stays an Int32; one that does not becomes a Double. The type of the result depends on the values, not on the expression, which matters as soon as a later line does something type-sensitive with it. If you want Bash-style truncation, cast it — but note that casting to [int] rounds, it does not chop:

powershell
[int](10 / 3)   # 3
[int](5 / 2)    # 2  <- rounds to even, not 3
[int](7 / 2)    # 4

Porting a script the other way, or want the same ground covered for Bash? See Math Arithmetic: How To Do Calculation in Bash?.

Watch the left operand when a value came from text

PowerShell decides what an operator means from the type of the left operand, then coerces the right one to match. Numbers read out of a file, a registry key, or an API response arrive as strings, and the results then diverge sharply:

powershell
"10" + 2    # 102    (string concatenation)
2 + "10"    # 12     (addition)
"10" * 2    # 1010   (string repeated)
2 * "10"    # 20     (multiplication)

Same two values, opposite results, decided by which side they sit on. Cast the parsed value before doing arithmetic with it and the ambiguity goes away:

powershell
$parsed = "10"
[int]$parsed + 2    # 12

Exponents and square roots

PowerShell has no exponentiation operator. 2 ** 3 does not evaluate to 8, it fails to parse:

text
You must provide a value expression following the '*' operator.

Use [Math]::Pow instead, and [Math]::Sqrt for square roots:

powershell
[Math]::Pow(2, 3)     # 8
[Math]::Pow(2, 10)    # 1024
[Math]::Sqrt(16)      # 4

[Math]::Pow always returns a Double, even when both arguments are whole numbers and the answer is exact. Cast it if you need an integer back:

powershell
[int][Math]::Pow(2, 10)   # 1024, as Int32

👉 [Math] and [System.Math] are the same type. [Math] -eq [System.Math] returns True and [Math].FullName is System.Math — PowerShell resolves the System. prefix for you. The short form is what most scripts use, and it is what this post uses throughout.

Rounding, absolute values, and precision

[Math]::Round rounds to the nearest whole number, or to a given number of decimal places:

powershell
[Math]::Round(3.14)        # 3
[Math]::Round(3.14159, 2)  # 3.14
[Math]::Abs(-7)            # 7
[Math]::Ceiling(2.1)       # 3
[Math]::Floor(2.9)         # 2

The default rounding mode is the one that surprises people:

powershell
[Math]::Round(2.5)    # 2
[Math]::Round(3.5)    # 4

.NET rounds halfway cases to the nearest even number, a convention known as banker’s rounding. It avoids the upward bias you get from always pushing .5 away from zero, which matters once you are summing thousands of rounded values. If you want the schoolbook behavior, ask for it explicitly:

powershell
[Math]::Round(2.5, [MidpointRounding]::AwayFromZero)   # 3

Anything reporting on money or quotas should either pick a mode deliberately or use [decimal], because [double] carries the usual binary floating-point error:

powershell
$x = 0.1 + 0.2
$x              # 0.3
$x -eq 0.3      # False

The shell prints 0.3 because it displays the shortest string that round-trips back to the stored value, not the value itself. Ask for full precision and the gap shows up:

powershell
(0.1 + 0.2).ToString('G17')   # 0.30000000000000004

[decimal] is base-10 and does not have the problem:

powershell
([decimal]0.1 + [decimal]0.2) -eq [decimal]0.3   # True

[decimal] is slower than [double] and covers a smaller range, which makes it the standard choice for currency and quota reporting, and a poor one for scientific work.

Trigonometry and logarithms

The rest of the .NET Math surface is reachable the same way. The trigonometric methods take radians, so degrees need converting first:

powershell
$pi = [Math]::PI
[Math]::Sin(30 * ($pi / 180))    # 0.5
[Math]::Cos(60 * ($pi / 180))    # 0.5
[Math]::Log(100, 10)             # 2
[Math]::Log10(1000)              # 3

Expect floating-point residue on angles that should come out clean: [Math]::Sin($pi) evaluates to 1.22464679914735E-16. Compare trigonometric results against a tolerance rather than with -eq.

Random numbers

For random numbers PowerShell gives you a cmdlet, Get-Random:

powershell
Get-Random -Minimum 1 -Maximum 100   # e.g. 74

-Maximum is exclusive, so that call returns 1 through 99. Get-Random also picks an element out of a collection, which is often what you actually want:

powershell
Get-Random -InputObject @('web01', 'web02', 'web03')

Doing math over a collection

Writing a loop to total a list is the long way round. Measure-Object takes a pipeline and returns the aggregate:

powershell
1..10 | Measure-Object -Sum -Average -Maximum -Minimum
text
Count             : 10
Average           : 5.5
Sum               : 55
Maximum           : 10
Minimum           : 1
StandardDeviation :
Property          :

The empty StandardDeviation line is there because it was not asked for. Add -StandardDeviation, or -AllStats for the lot.

With -Property it works against a field on an object, which is where it earns its place:

powershell
Get-ChildItem C:\logs | Measure-Object -Property Length -Sum

Pull individual values back out with a subexpression:

powershell
$stats = Get-ChildItem C:\logs | Measure-Object -Property Length -Sum -Average
"Total: $([Math]::Round($stats.Sum / 1GB, 2)) GB across $($stats.Count) files"

That covers the arithmetic most scripts need. For anything else, [Math] | Get-Member -Static lists the whole type in the console, which usually answers the question faster than a search engine will.