### Math Matters

Hate math? Hate it no longer when you invoke the .NET Math class for this week's data formatting tip.

I'm sure many of you have either seen code like this if not run it yourself:

PS C:\> Get-WmiObject win32_logicaldisk -filter "drivetype=3" | Select DeviceId,Size,Freespace

DeviceId Size Freespace

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

C: 201504845824 134099279872

D: 32499560448 5596352512

E: 209711104 135725056

You've probably also tried to reformat the number to something more meaningful, such as megabytes:

PS C:\> Get-WmiObject win32_logicaldisk -filter "drivetype=3" | Select DeviceID,@{Name="SizeMB";Expression={$_.Size/1MB}},@{Name="FreeMB";Expression={$_.Freespace/1MB}}

DeviceID SizeMB FreeMB

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

C: 192169.99609375 127881.6796875

D: 30993.99609375 5337.09765625

E: 199.99609375 129.4375

Of course very few people like all those decimal points. So you might try shortening them with this:

PS C:\> Get-WmiObject win32_logicaldisk -filter "drivetype=3" | Select DeviceID,@{Name="SizeMB";Expression={"{0:N2}" -f ($_.Size/1MB)}},

@{Name="FreeMB";Expression={"{0:N2}" -f ($_.Freespace/1MB)}}

DeviceID SizeMB FreeMB

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

C: 192,170.00 127,887.63

D: 30,994.00 5,337.10

E: 200.00 129.44

This certainly looks better and if all you want is a simple formatted report, this is fine. But what you see is not what you get. Look at this:

PS C:\> Get-WmiObject win32_logicaldisk -filter "drivetype=3" |

Select DeviceID,@{Name="SizeMB";Expression={"{0:N2}" -f ($_.Size/1MB)}},

@{Name="FreeMB";Expression={"{0:N2}" -f ($_.Freespace/1MB)}} | Sort FreeMB -Descending

DeviceID SizeMB FreeMB

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

D: 30,994.00 5,337.10

E: 200.00 129.44

C: 192,170.00 127,880.50

It's clearly not sorting in the expected order. That's because when you use the -f operator, it creates a string value. If you had a numeric value property from many machines you won't get the results you expect.

One solution is to convert this string back into a number:

PS C:\> Get-WmiObject win32_logicaldisk -filter "drivetype=3" |

Select DeviceID,@{Name="SizeMB";Expression={("{0:N2}" -f ($_.Size/1MB)) -as [double]}},@{Name="FreeMB";Expression={("{0:N2}" -f ($_.Freespace/1MB)) -as [double]}} | Sort FreeMB -Descending

DeviceID SizeMB FreeMB

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

C: 192170 127881.47

D: 30994 5337.1

E: 200 129.44

That's more like it, but it sure seems like a lot of work. Here's a better way using the .NET Math class.

There are no math cmdlets, but you can access the math library by using [Math]. You can't create a math object, but once you know the method, you can simply invoke it. Here's a one-liner to help show you the methods:

([math]).GetMethods() | sort name | Select Name -unique

Once you know the method, then you can run commands like this:

PS C:\> [math]::Sqrt(25)

5

PS C:\> [math]::Pow(2,10)

1024

PS C:\> [math]::Round(123.45678,2)

123.46

It's that last method that we're interested in. The method needs a number and number of decimal places. The best part is that it writes a numeric object, technically a double in this example, to the pipeline. Thus, we can modify our WMI query accordingly:

PS C:\> Get-WmiObject win32_logicaldisk -filter "drivetype=3" |

Select DeviceID,@{Name="SizeMB";Expression={[math]::Round($_.Size/1MB,2)}},

@{Name="FreeMB";Expression={[math]::Round($_.Freespace/1MB,2)}} | Sort FreeMB -Descending

DeviceID SizeMB FreeMB

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

C: 192170 127884.68

D: 30994 5337.1

E: 200 129.44

I haven't found a good and easy way to force PowerShell to include the trailing 0, but I can live with this. If you don't want any decimal points, simply eliminate the second parameter value in the Round() method. But now I have a way to get numeric data in the format I want without sacrificing anything.

About the Author

Jeffery Hicks is a multi-year Microsoft MVP in Windows PowerShell, Microsoft Certified Professional and an IT veteran with almost 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He works today as an independent author, trainer and consultant. Jeff is a regular contributor to a variety on online sites, as well as frequent speaker at technology conferences and user groups. Keep up with Jeff and his projects at http://jdhitsolutions.com/blog.