PowerShell Round to 2 Decimal Places (and Whole Numbers)

To round a number to 2 decimal places in PowerShell, use [Math]::Round($number, 2). To display it with exactly two decimals, use the format operator, '{0:N2}' -f $number, or .ToString('0.00'):

$price = 19.98765

[Math]::Round($price, 2)
'{0:N2}' -f $price
$price.ToString('0.00')

Output:

19.99
19.99
19.99

They look the same here, but they don’t return the same kind of value, and they don’t always round the same way. I ran every example in PowerShell 7.6 and Windows PowerShell 5.1 and show where they differ.

Round() returns a number, -f returns text

Use Round() when you’ll keep calculating, and -f or ToString() at the end, when you print or export:

$rounded   = [Math]::Round(1234.5678, 2)
$formatted = '{0:N2}' -f 1234.5678

"Round() returns a $($rounded.GetType().Name): $rounded"
"-f N2 returns a $($formatted.GetType().Name):  $formatted"
"Math still works on the Double: $($rounded * 2)"

Output:

Round() returns a Double: 1234.57
-f N2 returns a String:  1,234.57
Math still works on the Double: 2469.14

N2 also adds a thousands separator. Use F2 for two decimals without commas, or C for currency.

Why 2.5 rounds to 2

[Math]::Round uses banker’s rounding: a value exactly halfway goes to the nearest even number. So 2.5 becomes 2, while 3.5 becomes 4. [int] does the same:

foreach ($n in 0.5, 1.5, 2.5, 3.5) {
    '{0}  Round: {1}  AwayFromZero: {2}  [int]: {3}  N0: {4}' -f $n,
        [Math]::Round($n),
        [Math]::Round($n, [MidpointRounding]::AwayFromZero),
        [int]$n,
        ('{0:N0}' -f $n)
}

Output in PowerShell 7:

0.5  Round: 0  AwayFromZero: 1  [int]: 0  N0: 0
1.5  Round: 2  AwayFromZero: 2  [int]: 2  N0: 2
2.5  Round: 2  AwayFromZero: 3  [int]: 2  N0: 2
3.5  Round: 4  AwayFromZero: 4  [int]: 4  N0: 4
PowerShell Math Round banker's rounding vs AwayFromZero
Round() and [int] send 2.5 to 2, AwayFromZero sends it to 3 (PowerShell 7)

Add [MidpointRounding]::AwayFromZero to get the school rule, where 0.5 always rounds up. It’s covered in the MidpointRounding reference.

The N0 column changes between versions

In Windows PowerShell 5.1, format strings round halves away from zero, so its N0 column reads 1, 2, 3, 4. PowerShell 7 rounds them to even, like Round(). That shows up in prices too:

"{0:C}" -f 0.125
"{0:C}" -f 2.345
"{0:N1}" -f 0.25

Output in PowerShell 7:

$0.12
$2.35
0.2

Output in Windows PowerShell 5.1:

$0.13
$2.35
0.3

If a report must match to the cent across versions, round first with AwayFromZero and format after. Don’t let the format string do the rounding.

Use [decimal] for money

Normal numbers are stored in binary, so some decimal values can’t be stored exactly. The d suffix makes a [decimal] literal, which stores cents exactly:

"0.1 + 0.2 as Double:  $((0.1 + 0.2).ToString('R'))"
"0.1 + 0.2 as Decimal: $(0.1d + 0.2d)"

Output:

0.1 + 0.2 as Double:  0.30000000000000004
0.1 + 0.2 as Decimal: 0.3

For totals and taxes, cast to [decimal] or use the d suffix, then round once at the end:

$items = 19.99d, 4.25d, 12.10d
$total = 0d
foreach ($price in $items) { $total += $price }
$tax = [Math]::Round($total * 0.0825d, 2, [MidpointRounding]::AwayFromZero)

"Subtotal: {0:C}" -f $total
"Tax:      {0:C}" -f $tax
"Total:    {0:C}" -f ($total + $tax)

Output:

Subtotal: $36.34
Tax:      $3.00
Total:    $39.34

I added the prices in a loop because Measure-Object -Sum returns a Double. The tax uses 8.25%, the Texas state and local maximum, and C adds the dollar sign.

Round to the nearest whole number

Round() with no digits rounds to a whole number. Floor always goes down, Ceiling always goes up, and Truncate just drops the decimals:

foreach ($n in 7.8, 7.2, -7.8) {
    '{0,5}  Round: {1,3}  Floor: {2,3}  Ceiling: {3,3}  Truncate: {4,3}' -f $n,
        [Math]::Round($n), [Math]::Floor($n), [Math]::Ceiling($n), [Math]::Truncate($n)
}

Output:

  7.8  Round:   8  Floor:   7  Ceiling:   8  Truncate:   7
  7.2  Round:   7  Floor:   7  Ceiling:   8  Truncate:   7
 -7.8  Round:  -8  Floor:  -8  Ceiling:  -7  Truncate:  -7
PowerShell Math Round, Floor, Ceiling and Truncate on positive and negative numbers
Floor and Truncate differ for negative numbers (Windows PowerShell 5.1)

For -7.8, Floor gives -8 because that’s lower, while Truncate gives -7. Ceiling is handy for counts, like the number of boxes needed for 7.2 boxes’ worth of items.

Truncate to 2 decimals instead of rounding

Truncate has no digits option, so multiply by 100, truncate, then divide:

$rate = 4.3789

"Rounded to 2:   $([Math]::Round($rate, 2))"
"Truncated to 2: $([Math]::Truncate($rate * 100) / 100)"

Output:

Rounded to 2:   4.38
Truncated to 2: 4.37

Round Measure-Object results

Measure-Object returns full precision, which looks messy in reports. Round the property you need:

$stats = Get-ChildItem -Path C:\psfaqs\Round -File | Measure-Object -Property Length -Average -Sum

"Raw average:    $($stats.Average / 1MB) MB"
"Rounded:        $([Math]::Round($stats.Average / 1MB, 2)) MB"
"Total:          $('{0:N2}' -f ($stats.Sum / 1MB)) MB"

Output:

Raw average:    1.86879944801331 MB
Rounded:        1.87 MB
Total:          7.48 MB
PowerShell Measure-Object average rounded to 2 decimal places
The raw average has 14 decimals, Round() trims it to 1.87 (PowerShell 7)

Round inside Select-Object

For a table, round in a calculated property. The value stays a number, so sorting still works: