Rounding Numbers—PowerShell Style


Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to round numbers.

Hey, Scripting Guy! Question Hey, Scripting Guy! I think your series about formatting numbers has been pretty interesting. However, everything you have shown has a major problem—and that is that you convert numbers into strings. I would love to be able to display a Windows PowerShell number with a specific number of decimal places, but not have it be a string. Instead, I want it to be a number type. Can you do this? Or am I stuck with storing numbers and then converting them into strings before I display the results?

—GS

Hey, Scripting Guy! Answer Hello GS,

Microsoft Scripting Guy, Ed Wilson, is here. This morning, I decided to make a cup of Gunpowder green tea. I put a bit of lemon in it, and that is it. Gunpowder green tea seems to go well with kiwis—the flavors complement each other nicely. It is very refreshing. Normally, I drink a black tea in the morning, and then maybe have a cup of some sort of green tea in the afternoon. But I decided I wanted to start drinking more green tea.

I am sitting at my table, checking email sent to scripter@microsoft.com, and I ran across your email. GS, you are right. I have been focusing on methods that in the end convert the number to a string. So lets correct that right now.

Rounding a number with Windows PowerShell

To round a number in Windows PowerShell, all I need to do is to call the Round static method from the System.Math class. A static method just means that it is directly available from the class, and that I do not need to create an instance of it first. Because the Math class is in the System .NET Framework namespace, I can drop the initial System when I call the static method. I can therefore call the method like this:

PS C:\> [math]::Round(2.25)

2

Notice that by default, the Round method does not include any decimal places. The second parameter for the Round method permits me to specify how many places I wanted to include. This technique is shown here:

PS C:\> [math]::Round(2.25, 1)

2.2

Notice that here the decimal, .25, rounded down to .2. This is because the number (2) is even. In the following example, the .35 rounds up because the number (3) is odd.

PS C:\> [math]::Round(2.35, 1)

2.4

A practical example of rounding

File sizes in Windows PowerShell appear as bytes. This can make the numbers a bit difficult to read. Luckily, Windows PowerShell includes a number of admin constants to make the conversion from bytes to kilobytes or megabytes easier to accomplish. The problem is nearly as bad when it comes to file sizes because the conversion usually produces a long string of decimal places. The answer is to use the Round method and to select a number that is more easily digested.

In the following example, I use the Get-Item cmdlet to return information about a file that happens to reside on my hard drive. I then choose the Length property. That tells me the size of the file in bytes. I then convert the file size to megabytes and display the results. Following that, I use the Round method choose the default, and choose two decimal places. This is shown in the following output:

PS C:\> Get-Item C:\fso\epcisar.txt

    Directory: C:\fso

Mode             LastWriteTime     Length        Name                                                          

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

-a---         7/17/2014   3:33 PM    6531842 epcisar.txt                                                    

PS C:\> $a = Get-Item C:\fso\epcisar.txt

PS C:\> $a.Length / 1MB

6.22924995422363

PS C:\> [math]::round($a.Length / 1MB)

6

PS C:\> [math]::round($a.Length / 1MB, 2)

6.23

Now that I know what I want to do, I am going to display the name of the file and the size of the file in megabytes—but I am going to do it in a single line. To do this, I will use the Select-Object cmdlet and create a new property. I use a hash table to create the new property. For the label (l is my property alias), I use ‘size in MB’. The expression picks the length property from the pipeline.

In the following example, I first divide the length by 1 MB, and then I call the [math]::Round static method and tell it that I want two decimal places:

Get-Item C:\fso\epcisar.txt | select name, @{l='size in MB'; e={[math]::Round(($_.length /1MB),2)}}

The command and the output from the command are shown in the following image:

Image of command output

GS, that is all there is to using Windows PowerShell to round numbers. This also concludes Numbers Week. Join me tomorrow for PowerShell Spotlight when I will have guest post by Windows PowerShell MVP, Teresa Wilson (The Scripting Wife).

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Comments (1)

  1. A word of caution with the Math Round method. I have experienced it using "banker’s rounding" which means numbers are rounded to the nearest even number. This doesn’t follow the rules I learned with math rounding where something ending in 5 is always rounded
    up to the next higher level number. To get the Round function to behave the way most of us learned math rules, you use the additional AwayFromZero switch.

    There is a great write up that explains it better than I could here:
    http://www.madwithpowershell.com/2013/10/math-in-powershell.html

    The round statement with the AwayFromZero switch looks like this:
    [Math]::Round(12.345 ,2,"AwayFromZero")  yields  12.35 versus 12.34.

    I just wanted to drop this note because I got bit by this behavior once myself and almost didn’t catch it before it was too late. 🙂

Skip to main content