Two plus two equals "Monday" ?

Two plus two equals "Monday" ?

  • Comments 10

In PowerShell, two plus two does not always equal four. 

Why?  Because there are twos and there are twos.

Let me explain.  PowerShell does a ton of work on your behalf so you can think about what you want to do and not how to do it.  Think about the difference between an automatic transmission and a manual one.  An automatic does a ton of work on your behalf but sometimes it doesn't have the information to make the right decision.  That is why automatic transmissions allow you to shift into 1, 2 ,3  or D (which automatically shifts for you).  Occassionally, you need to override the decision making.  In the end, an automatic transmission is a pretty good deal. 

PowerShell is actually more like a tiptronic transmission (which is what I drive) which gives you the option of being automatic or manual giving you the best of both worlds..  Most people don't have experience with those so I'll just go with the automatic analogy. 

So back to two plus two.  Sometimes two is a string and sometimes it is an int.  So, to steal a little from Tolstoy - when then must we do? 

What PowerShell does is to use the type of the first element of the expression to type the expression.  If it is an number the addition is a numeric addition.  If it is a String, the addition is a string addition.  Ditto for multiplication.  Let me show you:

PS> 2+2
4
PS> 2+"2"
4
PS> "2"+"2"
22
PS> "2"+2
22
PS> 2 * 30
60
PS> "2" * 30
222222222222222222222222222222
PS> [Int]"2" + 2

PS> [INT]("2" + 2)
22
PS> [STRING]2 + 2
22
PS> [INT]$x = "2"
PS> $x + 2
4

 

Got your head around that one yet?  Try this one:

 

PS> [timespan]2 + 2


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 0
Ticks             : 4
TotalDays         : 4.62962962962963E-12
TotalHours        : 1.11111111111111E-10
TotalMinutes      : 6.66666666666667E-09
TotalSeconds      : 4E-07
TotalMilliseconds : 0.0004



PS> [DateTime]2 + 2

Monday, January 01, 0001 12:00:00 AM

 

I LOVE this stuff! 

Jeffrey Snover [MSFT]
Windows PowerShell/MMC Architect
Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

Leave a Comment
  • Please add 4 and 3 and type the answer here:
  • Post
  • "What PowerShell does is to use the type of the first element of the expression to type the expression."

    Well, not completely. If the type of the first expression is [int] the expression is always floating point, so:

    PS1> [int]1/2

    0.5

    (which is of type double)

  • Nice post... this is one of the best descriptions of how PoSH handles this that I've seen.  I spent a while tripping over bits of this before I realized what I was doing.  Consider it bookmarked for reference. ;)

  • Just wanted to kick out a heads up for an excellent post that shows some of the different variable types

  • From an earlier comment:

    >Well, not completely. If the type of the first expression is [int] the expression is always floating point, so:

    >

    > PS1> [int]1/2

    >

    > 0.5

    >

    > (which is of type double)

    That's not quite accurate as illustrated by these two examples:

    PS (11) > (6/3).gettype().fullname

    System.Int32

    PS (12) > (6/34).gettype().fullname

    System.Double

    For numeric operations, PowerShell uses widening. If the result of the operation cannot be exactly represented using the base types of the operation, then the next widest type that can hold the result will be used, within the limitations of the .NET numeric types (we don't support arbitrary precision yet.) This is what's happening here. 1/2 cannot be properly represented as an int to the result is widened to double (yes - we skip single precision).

    If you cast the whole expression to [int] then you'll get an integer result:

    PS (13) > [int](1/2)

    0

    Note that like VB, we use "banker's rounding" so

    PS (14) > [int](3/2)

    2

    Here we get 2 instead of 1. To get truncation, use [math]::floor()

    PS (15) > [math]::floor(3/2).gettype().FullName

    System.Double

    PS (16) > [math]::floor(3/2)

    1

    PS (17) > [int] [math]::floor(3/2)

    1

    The goal of all of this is to have "natural" behaviour for numbers.

    See Python PEP 238 for an additional discussion of this issue in Python.

    http://www.python.org/dev/peps/pep-0238/

    (We're currently missing a floor division operator unfortunately.)

    BTW - I spend a bunch of time in my book going over the semantics of all of the operators in (great) detail.

    -bruce

    Bruce Payette [MSFT]

    Windows PowerShell Tech Lead

    Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell

    Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

    My book:

    http://manning.com/powershell

  • Thanks Bruce for the qualification... I didn't realise the 6/3 would be an int.

    I think the main issue for me is that there is no 'floor division' operator; someone somewhere else suggested the pythonesque // for it.

    At least this could be added to PS1.1 without breaking backward compatibility.

  • I have noticed that you can also get truncation by using the decimal type.  

    [int][decimal](3/2).  

    Is there a reason you'd want to avoid this as opposed to using floor()?

  • That's interesting.

    I wouldn't use it though:

    PS> (measure-command { foreach($x in 1..10000) { [Math]::Floor(3/2) } }).totalmilliseconds

    64.0313

    PS> (measure-command { foreach($x in 1..10000) { [int][decimal](3/2) } }).totalmilliseconds

    660.2069

  • Development Karl Seguin does some testing on his blog about the fastest way to convert a string to an

  • this is stupid 2+2 equals 4 like always

  • Nice article. Just took it a step further, have a look how to blend integer and string into one: http://powershell.com/cs/blogs/tobias/archive/2010/01/08/1-equals-quot-running-quot-melting-integer-and-string-objects-together.aspx

Page 1 of 1 (10 items)