4

I've seen a notebook with the following:

FullSimplify[
 Solve[{eq1, eq2, eq3, eq4, eq5, eq6, eq7, eq8, eq9, eq10, eq11, eq12},
       {hbbbf, hbcf, hbbcr, hbcc, hbvbf, hbbc, hsbbf, hssd, hsvbf, hsf, hsbr, hsc}
 ]
][[1]] // N

I searched the Mathemtatica help documentation for // and it seems to be a postfix operator. On the other hand N seems to be a way to specify the precision of a numerical value.

What does the [[1]] // N mean?

Thanks.

rcollyer
  • 33,976
  • 7
  • 92
  • 191
dabd
  • 839
  • 4
  • 13

2 Answers2

19

Actually, // is not a postfix operator, itself; it would be considered an infix operator, akin to + or -. It operates by turning x // f into f[x]. You can string several of them together, e.g. x // f // g which is equivalent to g[f[x]], and think of them as successive transformations. This can be very useful for crafting complex transformations, but it does make for very opaque code. Nowadays, I tend to create many functions and layer them to create the effects which makes my code a bit easier to follow. Similarly, there is the prefix form f @ x which is operationally equivalent to x // f.

As pointed out in Michael's answer, the entire left hand side (LHS) must be considered as the argument to the right hand side (RHS) which usually works. There are cases where it will not, but that depends on the precedence of the operators used on the LHS. For most cases, there is nothing to worry about as // has a relatively low precedence, but consider the following

 f = x // g

The Set operator (=) has a lower precedence than //, so the above is equivalent to

f = g[x]

\begin{Edit}

Additionally, mixing operators with higher precedence can cause some confusion. For instance, the following

m // p + q // n

is interpreted as

n[ (p + q)[m] ]

which is not likely what you would want, so parentheses should be used, such as

(m // p) + q // n
(* n[q + p[m]] *)

or

(m // p) + (q // n)
(* n[q] + p[m] *)

depending on what you want.

It is interesting to note that the function operator (&) which turns the preceding into a pure function has a low precedence relative to most operators, but a higher precedence than //. So, this

m // p + q& // n

is interpreted as

n[ Function[ p + q ][m] ]

or

n[ p + q ]

if neither p nor q are slots.

\end{Edit}

Part ([[i]]), on the other hand, has a high precedence, so it will take effect prior to //, and it can be considered a postfix operator, also. In other words, it effects the output from FullSimplify prior to N being applied. Rewriting the code as it is interpreted, you get

N[ Part[ FullSimplify[ Solve[ ... ] ], 1 ] ]

But, I am partial to using the prefix form here

N @ FullSimplify[ ... ][[1]]

or, possibly more clearly

N @ First @ FullSimplify[ ... ]

as the intent of the code is clarified a bit by letting the user know they will be getting a numerical result up front. The shift to using First instead of Part[..., 1] only further clarifies what is occurring. The downside to this construct, as opposed to the postfix form, is it can be more difficult to add additional transformations while keeping them straight in your mind. For the so inclined, here is the full postfix form

FullSimplify[ ... ] // First // N

or, how I would write it

Solve[ ... ] // FullSimplify // First // N

Lastly, while N can be used to specify numerical precision, I primarily use it to convert from analytic numbers to numerical numbers. For instance, Mathematica is perfectly happy to work with 1/3, but sometimes I need a numerical answer. So, I use N to perform the conversion.

rcollyer
  • 33,976
  • 7
  • 92
  • 191
  • I see you decided to make something of this question. +1 :-) – Mr.Wizard Jan 06 '13 at 05:41
  • @Mr.Wizard every once in a while, you can turn a so-so question into a teaching moment, and expose and clarify misconceptions. Besides, that link to the operator precedence list is not as easy to find as I'd like (I know what to look for, so I can find it), so I like to have it referenced as often as possible. – rcollyer Jan 06 '13 at 06:52
  • Exactly. I'm glad to see you do it. – Mr.Wizard Jan 06 '13 at 06:53
  • 2
    @Mr.Wizard my goal: don't have mma.se become like the c++ tag on SO. Basic misconceptions can be answered, and should. Sometimes a nudge is all that is necessary, and that is what comments are for. But, occasionally they need a thorough analysis, otherwise they may persist, and this one caused enough mental friction with me, that I decided to knock it out of the park. – rcollyer Jan 06 '13 at 07:32
  • @badb, just let me add a link to the official operator precedence documentation. And as for a quick guide this one. – carlosayam Jan 06 '13 at 12:13
  • @caya I've included the operator precedence documentation already, that's what the link on the word precedence links to. – rcollyer Jan 06 '13 at 14:10
  • The low precedence can trip up a new user when they try to do something like expr1 // N + expr2 // N, assuming it's similar to N@expr1 + N@expr2 – rm -rf Jan 06 '13 at 18:27
  • @Hypnotoad good point. I updated my answer to include that. – rcollyer Jan 06 '13 at 19:50
  • The answer begins, "Actually, // is not a postfix operator, itself...". Yet the Documentation Center page ref/Postfix states: "Postfix[f[expr]] prints with f[expr] given in default postfix form expr // f." [emph added] (Sorry, the formatting here is getting messed up and does not seem to appear the way the help says it should.) – murray Jan 06 '13 at 20:12
  • @murray the difficulty with that documentation is it is describing a display form, not the action of // itself. Also, if you read the docs a little closer, you'll note that Postfix displays the postfix form of f, but it says nothing about //, directly. Based upon how it works, the action of // must be interpreted as a binary (or infix) operator. – rcollyer Jan 06 '13 at 20:22
  • @rcollyer: Yes, of course one may refer to // as an infix operator, since it takes both a left an a right argument. On the other hand, the use of "postfix" helps distinguish it from normal prefix placement f[x] (or f@x) and infix placement for a 2-argument function x ~f~ y. Both descriptions "postfix" and "infix" could therefore be justified. – murray Jan 07 '13 at 00:47
  • @murray you are correct, but I was trying to impress on the OP the semantics of //. And, while it is the postfix operator, I felt the infix semantics were what he was missing. – rcollyer Jan 08 '13 at 03:37
1
  1. [[1]] means part 1, the first element of the expression returned by FullSimplify. FullSimplify will return the simplified list of solutions (found by Solve) of the twelve equations.

  2. // N converts exact numbers to (approximate) Real numbers.

The right way to parse the expression is (FullSimplify[...][[1]]) // N.

Michael E2
  • 235,386
  • 17
  • 334
  • 747