Introduction to Mathematica, Part II

Mathematica can be used in the same fashion as a traditional programming language, such a fortran or C.  For  frequently used programs or computationally intensive applications, Mathematica is not the best programming language choice, but it can be very effective as a way to test out ideas or generate a single numerical result.

Evaluating a sequence of instrutions (;;;)

In[1]:=

a = 1 ;

 a = a + a ; a = a^a

 a = a + a ;   a = a^a

Out[2]=

4

Out[3]=

16777216

Note above that line breaks without ";" are points where the instructions get executed. This three-line sequence produces two lines of output and the instructions get executed sequentially.

In[4]:=

Clear [ a ]

Loops

In[5]:=

? Do

Do[expr, {imax}] evaluates expr imax times. Do[expr, {i, imax}] evaluates expr with the variable i successively taking on the values 1 through imax (in steps of 1). Do[expr, {i, imin, imax}] starts with i = imin. Do[expr, {i, imin, imax, di}] uses steps di. Do[expr, {i, imin, imax}, {j, jmin, jmax}, ... ] evaluates expr looping over different values of j, etc. for each i. More…

In[6]:=

a = 1 ; Do [ a = 2 a ; a = a ^ a , { i , 1 , 2 } ]

In[7]:=

a

Out[7]=

16777216

In this case, Do does not produce screen output. The following will and is a simple illustration of how formatted output can be programmed:

In[8]:=

a = 0.1 ; Do [ a = 2 a ; a = a ^ a ; Print [ iteration is , i , and a is , a ] , { i , 1 , 4 } ]

iteration is 1 and a is 0.7247796636776955 SequenceForm iteration is 1 and a is 0.7247796636776955

iteration is 2 and a is 1.7128571313347576 SequenceForm iteration is 2 and a is 1.7128571313347576

iteration is 3 and a is 67.90544396641754 SequenceForm iteration is 3 and a is 67.90544396641754

iteration is 4 and a is 4.739585766849046 × 10 289 SequenceForm iteration is 4 and a is 4.739585766849046*10^289

In[9]:=

Clear [ a ]

In[10]:=

? For

For[start, test, incr, body] executes start, then repeatedly evaluates body and incr until test fails to give True. More…

In[11]:=

For [ a = 0.1 ; i = 1 , i 4 , i ++ , a = 2 a ; a = a ^ a ; Print [ iteration is , i , and a is , a ] ]

iteration is 1 and a is 0.7247796636776955 SequenceForm iteration is 1 and a is 0.7247796636776955

iteration is 2 and a is 1.7128571313347576 SequenceForm iteration is 2 and a is 1.7128571313347576

iteration is 3 and a is 67.90544396641754 SequenceForm iteration is 3 and a is 67.90544396641754

iteration is 4 and a is 4.739585766849046 × 10 289 SequenceForm iteration is 4 and a is 4.739585766849046*10^289

In[12]:=

? While

While[test, body] evaluates test, then body, repetitively, until test first fails to give True. More…

In[13]:=

? Table

Table[expr, {imax}] generates a list of imax copies of expr. Table[expr, {i, imax}] generates a list of the values of expr when i runs from 1 to imax. Table[expr, {i, imin, imax}] starts with i = imin. Table[expr, {i, imin, imax, di}] uses steps di. Table[expr, {i, imin, imax}, {j, jmin, jmax}, ... ] gives a nested list. The list associated with i is outermost. More…

In[14]:=

Clear [ a ]

In[15]:=

a = 0.25 ;

Table[{i, a = 2a ; a = a^a}, {i, 1, 4}]

Out[16]=

{ { 1 , 0.7071067811865476 } , { 2 , 1.632526919438153 } , { 3 , 47.629897842887345 } , { 4 , 3.239877051695713 × 10 188 } }

Note above that we have asked Mathematica to create a list of two-element lists...

In[17]:=

a = 0.75 ;

Table[{i, a = 2a ; a = a^a}, {i, 1, 4}]

General :: ovfl : Overflow occurred in computation. More… "Overflow occurred in computation. \\!\\(\\*ButtonBox[\\\"More\[Ellipsis]\\\", ButtonStyle->\\\"RefGuideLinkText\\\", ButtonFrame->None, ButtonData:>\\\"General::ovfl\\\"]\\)"

Out[18]=

{ { 1 , 1.8371173070873836 } , { 2 , 119.27673125406582 } , { 3 , 1.518123145603 × 10 567 } , { 4 , Overflow [ ] } }

In[19]:=

datatable = Table [ { dx , For [ a = dx ; i = 1 , i 4 , i ++ , a = 2 a ; a = a ^ a ] ; Log [ a ] } , { dx , 0.01 , 0.5 , 0.01 } ]

Out[19]=

{ { 0.01 , 2196209.831078381 } , { 0.02 , 174326.3490924932 } , { 0.03 , 35352.12042223693 } , { 0.04 , 11659.73699584849 } , { 0.05 , 5160.679000648275 } , { 0.06 , 2774.129830784761 } , { 0.07 , 1709.115287254924 } , { 0.08 , 1163.813236887732 } , { 0.09 , 855.1756872220971 } , { 0.1 , 667.0030416162073 } , { 0.11 , 545.7785022440597 } , { 0.12 , 464.53616933146253 } , { 0.13 , 408.6853919352427 } , { 0.14 , 369.874854582954 } , { 0.15 , 343.1158401467583 } , { 0.16 , 325.34256153938776 } , { 0.17 , 314.65301398906865 } , { 0.18 , 309.8930864623196 } , { 0.19 , 310.4245780662861 } , { 0.2 , 315.99847458228123 } , { 0.21 , 326.69390733764703 } , { 0.22 , 342.9036158180131 } , { 0.23 , 365.3586713620991 } , { 0.24 , 395.1936770180245 } , { 0.25 , 434.0615328649573 } , { 0.26 , 484.3164443170436 } , { 0.27 , 549.2978198578503 } , { 0.28 , 633.7701037687876 } , { 0.29 , 744.611423186881 } , { 0.3 , 891.910076078108 } , { 0.31 , 1090.746929869923 } , { 0.32 , 1364.162148948438 } , { 0.33 , 1748.224638650612 } , { 0.34 , 2300.948432977562 } , { 0.35000000000000003 , 3118.479960503817 } , { 0.36 , 4365.524149365334 } , { 0.37 , 6334.759963246554 } , { 0.38 , 9567.85080734066 } , { 0.39 , 15113.63290219343 } , { 0.4 , 25108.13438026848 } , { 0.41000000000000003 , 44154.54944761085 } , { 0.42 , 82823.8958326237 } , { 0.43 , 167197.9159677453 } , { 0.44 , 367081.4766286009 } , { 0.45 , 887435.851786677 } , { 0.46 , 2397386.772755296 } , { 0.47000000000000003 , 7364787.78097261 } , { 0.48 , 2.627083529923603 × 10 7 } , { 0.49 , 1.115726317857784 × 10 8 } , { 0.5 , 5.814539984022602 × 10 8 } }

In the instruction above, note that the variable "datatable" is a list. In Mathematica, variables can be numbers, expressions, lists, plots, ...  We will see that this feature is very useful.

In[20]:=

ListPlot [ datatable ]

[Graphics:HTMLFiles/Lecture-03_8.gif]

Out[20]=

Graphics

In[21]:=

Options [ ListPlot ]

Out[21]=

{ AspectRatio 1 GoldenRatio , Axes Automatic , AxesLabel None , AxesOrigin Automatic , AxesStyle { Thickness [ 0.01 ] } , Background Automatic , ColorOutput Automatic , DefaultColor Automatic , DefaultFont $DefaultFont , DisplayFunction $DisplayFunction , Epilog { } , FormatType $FormatType , Frame False , FrameLabel None , FrameStyle Automatic , FrameTicks Automatic , GridLines None , ImageSize Automatic , PlotJoined False , PlotLabel None , PlotRange Automatic , PlotRegion Automatic , PlotStyle { { Thickness [ 0.0075 ] , PointSize [ 0.01 ] } } , Prolog { } , RotateLabel True , TextStyle $TextStyle , Ticks Automatic }

Note that the options are written as Rules.

In[22]:=

ListPlot [ datatable , PlotRange { 250 , 500 } ]

[Graphics:HTMLFiles/Lecture-03_9.gif]

Out[22]=

Graphics

In[23]:=

? *Minimum*

FindMinimum[f, {x, x0}] searches for a local minimum in f, starting from the point x=x0. FindMinimum[f, {{x, x0}, {y, y0}, ... }] searches for a local minimum in a function of several variables. More…

In[24]:=

FindMinimum [ For [ a = dx ; i = 1 , i 4 , i ++ , a = 2 a ; a = a ^ a ] ; Log [ a ] , { dx , 0.15 , 0.25 } ]

Out[24]=

{ 309.4923784392815 , { dx 0.18393972042840706 } }

By going into the Help Browser, you can see that the output of FindMinimum is a list, the first element of which is the functions minimum value, and the second is a Rule specifing where the minimum occurs.

Lets try and do the above the hard way.  I will use Nest to recursively apply the function 4 times (I am just using a shorthand here, we can ignore the use of Nest for this course...). You can see that it works. Don't worry about it, but if you want to know about it, use the Help Browser to get information about Nest and Pure Functions.

In[25]:=

Clear [ x ]

In[26]:=

fx = Nest [ ( 2 # ) ^ ( 2 # ) & , x , 4 ]

Out[26]=

( 2 1 + 2 ( 2 1 + 2 x x 2 x ) 2 1 + 2 x x 2 x ( ( 2 1 + 2 x x 2 x ) 2 1 + 2 x x 2 x ) 2 ( 2 1 + 2 x x 2 x ) 2 1 + 2 x x 2 x ) 2 1 + 2 ( 2 1 + 2 x x 2 x ) 2 1 + 2 x x 2 x ( ( 2 1 + 2 x x 2 x ) 2 1 + 2 x x 2 x ) 2 ( 2 1 + 2 x x 2 x ) 2 1 + 2 x x 2 x

Take it derivative and set equal to zero...

In[27]:=

dfx = D [ fx , x ] // Simplify

Out[27]=

4 ( 2 1 + 2 x x 2 x ) 1 + 2 1 + 2 x x 2 x ( 2 1 + 2 ( 2 1 + 2 x x 2 x ) 2 1 + 2 x x 2 x ( ( 2 1 + 2 x x 2 x ) 2 1 + 2 x x 2 x ) 2 ( 2 1 + 2 x x 2 x ) 2 1 + 2 x x 2 x ) 1 + 2 1 + 2 ( 2 1 + 2 x x 2 x ) 2 1 + 2 x x 2 x ( ( 2 1 + 2 x x 2 x ) 2 1 + 2 x x 2 x ) 2 ( 2 1 + 2 x x 2 x ) 2 1 + 2 x x 2 x ( 1 + Log [ 2 x ] ) ( 1 + Log [ 2 1 + 2 x x 2 x ] ) ( 1 + Log [ 2 ( 2 1 + 2 x x 2 x ) 2 1 + 2 x x 2 x ] ) ( 1 + Log [ 2 1 + 2 ( 2 1 + 2 x x 2 x ) 2 1 + 2 x x 2 x ( ( 2 1 + 2 x x 2 x ) 2 1 + 2 x x 2 x ) 2 ( 2 1 + 2 x x 2 x ) 2 1 + 2 x x 2 x ] )

Finding the zero of this will not be easy.... but FindRoot claims it can do it...

In[28]:=

FindRoot [ dfx , { x , .1 , .3 } ]

Out[28]=

{ x 0.18393972058572117 }

Local Variables

In the above, the values of a and  dx are used repeatly—however, if we are only interested in the resulting minimum, their final values have little meaning or importance.  Suppose, we use the value of a or dx without clearing—what will the value be?

In[29]:=

dx

a

Out[29]=

dx

Out[30]=

( 2 1 + 2 ( 2 1 + 2 dx dx 2 dx ) 2 1 + 2 dx dx 2 dx ( ( 2 1 + 2 dx dx 2 dx ) 2 1 + 2 dx dx 2 dx ) 2 ( 2 1 + 2 dx dx 2 dx ) 2 1 + 2 dx dx 2 dx ) 2 1 + 2 ( 2 1 + 2 dx dx 2 dx ) 2 1 + 2 dx dx 2 dx ( ( 2 1 + 2 dx dx 2 dx ) 2 1 + 2 dx dx 2 dx ) 2 ( 2 1 + 2 dx dx 2 dx ) 2 1 + 2 dx dx 2 dx

In[31]:=

CurrentValueofA = a ;

As this could cause problems if a is used in a function call, say Sin[2 π a], it is a good idea to localize variables.

In[32]:=

? Module

Module[{x, y, ... }, expr] specifies that occurrences of the symbols x, y, ... in expr should be treated as local. Module[{x = x0, ... }, expr] defines initial values for x, ... . More…

In[33]:=

dx = SnickerDoodle ; a = HappyGoLucky ;

0.18393972042840706

In[35]:=

dx

a

solution

Out[35]=

SnickerDoodle

Out[36]=

HappyGoLucky

Out[37]=

solution

Switches: If, Which

In[38]:=

? If

If[condition, t, f] gives t if condition evaluates to True, and f if it evaluates to False. If[condition, t, f, u] gives u if condition evaluates to neither True nor False. More…

In[39]:=

a = Prime [ 23 ] + Prime [ 62 ] + Prime [ 104 ]

Out[39]=

945

In[40]:=

? PrimeQ

PrimeQ[expr] yields True if expr is a prime number, and yields False otherwise. More…

In[41]:=

If [ PrimeQ [ a ] , Print [ a , is a Prime Number ] , Print [ a , is not Prime, its divisors are , Divisors [ a ] ] , Print [ I have no idea what you are asking me to do! ] ]

945 is not Prime, its divisors are { 1 , 3 , 5 , 7 , 9 , 15 , 21 , 27 , 35 , 45 , 63 , 105 , 135 , 189 , 315 , 945 } SequenceForm 945 is not Prime, its divisors are 1 3 5 7 9 15 21 27 35 45 63 105 135 189 315 945

The above program is ok, but not very useful because it only works for  the current value of a.  It would be more useful to have something that worked for any value of a and could use it over again—that is, turn it into a tool.  This involves patterns and function definitions.

Patterns (_)

Patterns and Pattern Replacement are probably one of the most powerful features of Mathematica.  The underscore _ stands for a pattern,  a symbol x with an underscore (x_) is recognized as anypattern that matches x.  Here are some examples.

In[42]:=

AList = { first , second , third = 2 first , fourth = 2 second }

General :: spell1 : Possible spelling error: new symbol name \" AList \" is similar to existing symbol \" List \". More… "Possible spelling error: new symbol name \\\"\\!\\(AList\\)\\\" is similar to existing symbol \\\"\\!\\(List\\)\\\". \\!\\(\\*ButtonBox[\\\"More\[Ellipsis]\\\", ButtonStyle->\\\"RefGuideLinkText\\\", ButtonFrame->None, ButtonData:>\\\"General::spell1\\\"]\\)"

General :: spell1 : Possible spelling error: new symbol name \" first \" is similar to existing symbol \" First \". More… "Possible spelling error: new symbol name \\\"\\!\\(first\\)\\\" is similar to existing symbol \\\"\\!\\(First\\)\\\". \\!\\(\\*ButtonBox[\\\"More\[Ellipsis]\\\", ButtonStyle->\\\"RefGuideLinkText\\\", ButtonFrame->None, ButtonData:>\\\"General::spell1\\\"]\\)"

General :: spell1 : Possible spelling error: new symbol name \" second \" is similar to existing symbol \" Second \". More… "Possible spelling error: new symbol name \\\"\\!\\(second\\)\\\" is similar to existing symbol \\\"\\!\\(Second\\)\\\". \\!\\(\\*ButtonBox[\\\"More\[Ellipsis]\\\", ButtonStyle->\\\"RefGuideLinkText\\\", ButtonFrame->None, ButtonData:>\\\"General::spell1\\\"]\\)"

General :: stop : Further output of General :: spell1 will be suppressed during this calculation. More… "Further output of \\!\\(General :: \\\"spell1\\\"\\) will be suppressed during this calculation. \\!\\(\\*ButtonBox[\\\"More\[Ellipsis]\\\", ButtonStyle->\\\"RefGuideLinkText\\\", ButtonFrame->None, ButtonData:>\\\"General::stop\\\"]\\)"

Out[42]=

{ first , second , 2 first , 2 second }

In[43]:=

AList /. { 2 a_ a }

Out[43]=

{ first , second , 945 , 945 }

Here's a way to put the last input command into words: Search list AList for any pattern that matches "2 × anything" and replace "2 × anything" with a, then output the new AList. Study the following examples carefully:

In[44]:=

Clear [ a ]

In[45]:=

AList /. { 2 a_ a }

Out[45]=

{ first , second , first , second }

In[46]:=

AList /. { p_ , q_ , r_ , s_ } { p , p q , p q r , p q r s }

Out[46]=

{ first , first second , 2 first 2 second , 4 first 2 second 2 }

A qualifier on a pattern can be used to restrict which expressions will match the pattern:

In[47]:=

{ 2 , 0.667 , a / b , Pi } /. { p_Integer p One }

Out[47]=

{ 2 One , 0.667 , a b - One , π }

The third member of this result may be a bit surprising; it has to do with the way Mathematica internalizes expressions. In this case it represents the fraction as a b - 1 and it performs the replacement on the exponent (note that it must treat the "-" sign independently of the "1", as it returns "-One" rather than "One"…).

_ all by itself stands for anything.  x_ also  stands for anything, but gives anything a name for later use.

In[48]:=

AList /. _ AppleDumplings

Out[48]=

AppleDumplings

This is not very useful and it really is doing what you asked for—the first thing it found was AList itself and replaced AList with AppleDumplings.
x^n_
stands for x to any power, and the power can be refered to as n; x_^n_  stands for any expression raised to a power.  We can use these ideas to find rules that look like derivatives (this is not a good way to make a symbolic derivative, but it is illustrative):

In[49]:=

PaulieNoMealX = Sum [ b [ i ] x ^ i , { i , 2 , 6 } ]

Out[49]=

x 2 b [ 2 ] + x 3 b [ 3 ] + x 4 b [ 4 ] + x 5 b [ 5 ] + x 6 b [ 6 ]

In[50]:=

PaulieNoMealX /. x ^ n_ n x ^ ( n - 1 )

Out[50]=

2 x b [ 2 ] + 3 x 2 b [ 3 ] + 4 x 3 b [ 4 ] + 5 x 4 b [ 5 ] + 6 x 5 b [ 6 ]

This is ok, but it has least two problems.  The first is that it would be nice to have the rule work for any polynomial...

In[51]:=

DerivRule = q_ ^ n_ n q ^ ( n - 1 ) ;

In[52]:=

PaulineOMealY = Sum [ c [ i ] z ^ i , { i , 2 , 6 } ]

Out[52]=

z 2 c [ 2 ] + z 3 c [ 3 ] + z 4 c [ 4 ] + z 5 c [ 5 ] + z 6 c [ 6 ]

In[53]:=

PaulineOMealY/.DerivRule

PaulieNoMealX/.DerivRule

Out[53]=

2 z c [ 2 ] + 3 z 2 c [ 3 ] + 4 z 3 c [ 4 ] + 5 z 4 c [ 5 ] + 6 z 5 c [ 6 ]

Out[54]=

2 x b [ 2 ] + 3 x 2 b [ 3 ] + 4 x 3 b [ 4 ] + 5 x 4 b [ 5 ] + 6 x 5 b [ 6 ]

Another problem is that it will not work for first-order and zeroeth-order terms...

In[55]:=

PaulENoMiel = Sum [ c [ i ] HoneyBee ^ i , { i , 0 , 6 } ]

Out[55]=

c [ 0 ] + HoneyBee c [ 1 ] + HoneyBee 2 c [ 2 ] + HoneyBee 3 c [ 3 ] + HoneyBee 4 c [ 4 ] + HoneyBee 5 c [ 5 ] + HoneyBee 6 c [ 6 ]

In[56]:=

PaulENoMiel /. DerivRule

Out[56]=

c [ 0 ] + HoneyBee c [ 1 ] + 2 HoneyBee c [ 2 ] + 3 HoneyBee 2 c [ 3 ] + 4 HoneyBee 3 c [ 4 ] + 5 HoneyBee 4 c [ 5 ] + 6 HoneyBee 5 c [ 6 ]

This could be fixed, but it would be much easier to do so by defining functions of a pattern.


It is also possible to have a pattern apply conditionally using a condition. Here is an example that pulls out cases where the first member of a pair of numbers is less than the second.

In[57]:=

? Cases

Cases[{e1, e2, ... }, pattern] gives a list of the ei that match the pattern. Cases[{e1, ... }, pattern -> rhs] gives a list of the values of rhs corresponding to the ei that match the pattern. Cases[expr, pattern, levspec] gives a list of all parts of expr on levels specified by levspec which match the pattern. Cases[expr, pattern -> rhs, levspec] gives the values of rhs which match the pattern. Cases[expr, pattern, levspec, n] gives the first n parts in expr which match the pattern. More…

In[58]:=

Cases [ { { 1 , 2 } , { 2 , 1 } , { a , b } , { 2 , 84 } , 5 } , { first_ , second_ } /; first < second ]

Out[58]=

{ { 1 , 2 } , { 2 , 84 } }

Defining Functions with Patterns

Defining functions with patterns probably combines the most useful aspects of Mathematica.  Define a function that takes patten matching x as its first argument and an argument matching n as its second argument and returns x to the n th power:

In[59]:=

f [ x_ , a_ ] = x ^ a ; (* This is not a good way to define a function , we will see why later *)

What happens above is the right–hand–side is evaluated immediately , and its value is assigned to f [ a , b ] . It was probably intended that f [ 2 , 3 ] should always return 8 and that f [ y , z ] should always return y z , but this is not what Mathematica was asked to do :

In[60]:=

f[2, 3]

f[y, z]

Out[60]=

8

Out[61]=

y z

This works fine, but suppose we had defined  x ahead of time

In[62]:=

x = 4

Out[62]=

4

In[63]:=

f [ x_ , a_ ] = x ^ a ; (* This is not a good way to define a function , we will see why later *)

RHS evaluated, it is x^(second argument) which is currently 4^(second argument)

In[64]:=

f [ 2 , 3 ] (* should now be 4 ^ 3 , which is probably not what the programmer had in mind *)

Out[64]=

64

In[65]:=

f [ y , z ]

Out[65]=

4 z

Delayed Assignmet (:=)

The problem with the above functions is that the evaluation is made immediately.  For a function, the argument serves as a placeholder for a future calculation.  You do not wish to have the right–hand–side evaluated until the actual values of left–hand–side are specified.  The remedy is to use delayed assignment :=

In[66]:=

x = 4

a = ScoobyDoo

Out[66]=

4

Out[67]=

ScoobyDoo

In[68]:=

f [ x_ , a_ ] := x ^ a

In[69]:=

f [ 2 , 5 ]

Out[69]=

32

In[70]:=

f [ y , z ]

Out[70]=

y z

In[71]:=

f [ x , a ]

Out[71]=

4 ScoobyDoo

In[72]:=

f [ a , x ]

Out[72]=

ScoobyDoo 4

In[73]:=

Clear [ f ]

Functional Programming with Rules

The canonical programming example is the factorial function n! = (n)×(n-1) ×(n-2)×…×(1) where 0! ≡  1; here is a reasonably clever way to use the fact that (n+1)! = (n+1)×n!

In[74]:=

factorial [ n_ ] := n factorial [ n - 1 ]

General :: spell1 : Possible spelling error: new symbol name \" factorial \" is similar to existing symbol \" Factorial \". More… "Possible spelling error: new symbol name \\\"\\!\\(factorial\\)\\\" is similar to existing symbol \\\"\\!\\(Factorial\\)\\\". \\!\\(\\*ButtonBox[\\\"More\[Ellipsis]\\\", ButtonStyle->\\\"RefGuideLinkText\\\", ButtonFrame->None, ButtonData:>\\\"General::spell1\\\"]\\)"

This is part of definition, try it out...

In[75]:=

factorial [ 8 ]

$RecursionLimit :: reclim : Recursion depth of 256 exceeded. More… "Recursion depth of \\!\\(256\\) exceeded. \\!\\(\\*ButtonBox[\\\"More\[Ellipsis]\\\", ButtonStyle->\\\"RefGuideLinkText\\\", ButtonFrame->None, ButtonData:>\\\"$RecursionLimit::reclim\\\"]\\)"

Out[75]=

0

Ooops, Mathematica does not know when to quit.  Add the second part of the definition.

In[76]:=

factorial [ 0 ] = 1 ;

In[77]:=

factorial [ 120 ]

Out[77]=

6689502913449127057588118054090372586752746333138029810295671352301633557244962989366874165271984981308157637893214090552534408589408121859898481114389650005964960521256960000000000000000000000000000

In[78]:=

factorial [ 257 ]

$RecursionLimit :: reclim : Recursion depth of 256 exceeded. More… "Recursion depth of \\!\\(256\\) exceeded. \\!\\(\\*ButtonBox[\\\"More\[Ellipsis]\\\", ButtonStyle->\\\"RefGuideLinkText\\\", ButtonFrame->None, ButtonData:>\\\"$RecursionLimit::reclim\\\"]\\)"

Out[78]=

110229584131555281054302071911038392332774925355913902151965751073479124653079465235001077439818005985873301266490251083341199793258139997078914173571919244299833397234392889057883764180043100984153999534340466915039716962174069013215130571403957024607852812239029416823916860877192207891191648500255766086317527487056390542792833954544086850898277372666249856123600104664024185044015000245668519571915421777716404880622900435061328595982563147776000000000000000000000000000000000000000000000000000000000000000 Hold [ factorial [ 3 - 1 ] ]

In[79]:=

$RecursionLimit

Out[79]=

256

In[80]:=

$RecursionLimit = 2 ^ 24

Out[80]=

16777216

In[81]:=

Timing [ factorial [ 2000 ] ] [ [ 1 ] ]

Out[81]=

0.013481000000000076 Second

Using immediate assignment in a function: spending memory to buy time.

In[82]:=

factorial [ n_ ] := factorial [ n ] = n * factorial [ n - 1 ]

In[83]:=

Timing [ factorial [ 2000 ] ] [ [ 1 ] ]

Out[83]=

0.030232999999999954 Second

In[84]:=

Timing [ factorial [ 2001 ] ] [ [ 1 ] ]

Out[84]=

0.00007200000000029405 Second

In[85]:=

Clear [ factorial ]

Functions and Patterns with Restricted Rules

The factorial function is pretty good, but not foolproof:

In[86]:=

Clear [ factorial ]

In[4]:=

factorial [ 0 ] = 1 ; factorial [ n_ ] := n * factorial [ n - 1 ]

In[5]:=

factorial [ Pi ]

$RecursionLimit :: reclim : Recursion depth of 256 exceeded. More… "Recursion depth of \\!\\(256\\) exceeded. \\!\\(\\*ButtonBox[\\\"More\[Ellipsis]\\\", ButtonStyle->\\\"RefGuideLinkText\\\", ButtonFrame->None, ButtonData:>\\\"$RecursionLimit::reclim\\\"]\\)"

$RecursionLimit :: reclim : Recursion depth of 256 exceeded. More… "Recursion depth of \\!\\(256\\) exceeded. \\!\\(\\*ButtonBox[\\\"More\[Ellipsis]\\\", ButtonStyle->\\\"RefGuideLinkText\\\", ButtonFrame->None, ButtonData:>\\\"$RecursionLimit::reclim\\\"]\\)"

$RecursionLimit :: reclim : Recursion depth of 256 exceeded. More… "Recursion depth of \\!\\(256\\) exceeded. \\!\\(\\*ButtonBox[\\\"More\[Ellipsis]\\\", ButtonStyle->\\\"RefGuideLinkText\\\", ButtonFrame->None, ButtonData:>\\\"$RecursionLimit::reclim\\\"]\\)"

General :: stop : Further output of $RecursionLimit :: reclim will be suppressed during this calculation. More… "Further output of \\!\\($RecursionLimit :: \\\"reclim\\\"\\) will be suppressed during this calculation. \\!\\(\\*ButtonBox[\\\"More\[Ellipsis]\\\", ButtonStyle->\\\"RefGuideLinkText\\\", ButtonFrame->None, ButtonData:>\\\"General::stop\\\"]\\)"

Out[5]=

( - 253 + π )

The remedy is to restrict the pattern:

In[6]:=

Clear [ factorial ]

In[7]:=

factorial [ 0 ] = 1 ; factorial [ n_Integer ] := n * factorial [ n - 1 ]

In[8]:=

factorial [ Pi ]

Out[8]=

factorial [ π ]

Still not perfect:

In[9]:=

factorial [ - 5 ]

$RecursionLimit :: reclim : Recursion depth of 256 exceeded. More… "Recursion depth of \\!\\(256\\) exceeded. \\!\\(\\*ButtonBox[\\\"More\[Ellipsis]\\\", ButtonStyle->\\\"RefGuideLinkText\\\", ButtonFrame->None, ButtonData:>\\\"$RecursionLimit::reclim\\\"]\\)"

Out[9]=

- 613813439236565582550881087436617287705057171844406564133221284852668505630673002161103499723626566332335478102450963157585471048757952573733933575535232311883622272499716802718825740836570007830261546406974890016398663903866303300088454586862934691528828384953035307583981039794644809642100694673674233451659151811673510737541895875878747629227057549692012323824267182821618674417597528868005151236211026169213800577748621072639008286728902888390656000000000000000000000000000000000000000000000000000000000000000 Hold [ factorial [ - 259 - 1 ] ]

In[10]:=

Clear [ factorial ]

In[11]:=

factorial [ 0 ] = 1 ; factorial [ n_Integer ? Positive ] := n * factorial [ n - 1 ]

In[12]:=

factorial [ 12 ]

Out[12]=

479001600

In[13]:=

factorial [ Pi ]

Out[13]=

factorial [ π ]

As a last example, let's define the Sign function. It should be -1 when its argument is negative, 0 when its argument is zero, and +1 when its argument is positive.  There are lots of ways to write this function, there is no best way. Whatever works is good.

In[14]:=

? Sign

Sign[x] gives -1, 0 or 1 depending on whether x is negative, zero, or positive. More…

In[15]:=

HeyWhatsYourSign [ 0 ] = 0 ; HeyWhatsYourSign [ _ ? Positive ] := 1 ; HeyWhatsYourSign [ _ ? Negative ] := - 1 ;

In[16]:=

Plot [ HeyWhatsYourSign [ argument ] , { argument , - π , } ]

[Graphics:HTMLFiles/Lecture-03_23.gif]

Out[16]=

Graphics

In[17]:=

Plot [ { 1 / x , HeyWhatsYourSign [ x ] / x } , { x , - 1 , 1 } , PlotStyle { { Hue [ 1 ] , Thickness [ 0.02 ] } , { Hue [ 0.66 ] , Thickness [ 0.01 ] } } ]

[Graphics:HTMLFiles/Lecture-03_24.gif]

Out[17]=

Graphics


Created by Mathematica  (September 12, 2005) Valid XHTML 1.1!