Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Here's my problem:

My functions:

Xhcmaleorfemale[maleorfemale_,h_] := 
 Which[ (h<3|h>7),0,(h>2&&h<8),
  Which[maleorfemale==0,Xhcmale,maleorfemale==1,Xhcfemale][[h-2]] ];

X[t_,h_,region_,hc_,nh_,maleorfemale_] := 
  ((1+growthLTC)^(t/12))*(Which[ hc==1,Xhcmaleorfemale[maleorfemale,h],
   nh==1,Xnh [[region]] ]);

Xhcmale and Xhcfemale are two lists defined this way:

Xhcmale={45.33,113.12,215.22,312.67,449.85};
Xhcfemale={77.76,113.12,215.22,312.67,449.85};

Now I want to test the functions to see the results:

X[0,1,1,1,0,1] (* technically 0 in the 1st argument and 1 in the 4th or 5th is not possible but just for a test *)
X[12,3,1,1,0,1]
X[12,7,1,1,0,1]

The results should be:

0
(1+.035)^(12/12)*77.76=80.4816
(1+.035)^(12/12)*449.85=465.595

Instead this is what I get:

1. Which[True | False, 0, 1 > 2 && 1 < 8, 
  Which[1 == 0, Xhcmale, 1 == 1, Xhcfemale][[1 - 2]]]

80.4816

465.595

I have often this problem with Which and If functions. What am I doing wrong or what should I change? Thanks a lot, answers have been rapidly coming.

share|improve this question
2  
Don't use | use the logical Or || in (h<3|h>7) –  Matariki May 10 '13 at 11:52
add comment

closed as too localized by Yves Klett, Artes, m_goldberg, Sjoerd C. de Vries, Silvia May 10 '13 at 19:16

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.If this question can be reworded to fit the rules in the help center, please edit the question.

1 Answer

As Matariki pointed out in comments, this is a simple syntax error. The infix version of Or in Mathematica is ||, not |.

Change this, like so:

Xhcmaleorfemale[maleorfemale_, h_] := 
  Which[(h < 3 || h > 7), 0, (h > 2 && h < 8), 
   Which[maleorfemale == 0, Xhcmale, maleorfemale == 1, 
     Xhcfemale][[h - 2]]];

And you will get sensible answers, bearing in mind that growthLTC wasn't defined in your question.

In[38]:= X[0, 1, 1, 1, 0, 1]    
Out[38]= 0

In[39]:= X[12, 3, 1, 1, 0, 1]    
Out[39]= 77.76 (1 + growthLTC)

In[40]:= X[12, 7, 1, 1, 0, 1]    
Out[40]= 449.85 (1 + growthLTC)

As a general comment on your code, I think you would find it useful to use Condition statements and pattern matching in your definition of Xhcmaleorfemale to exclude nonsense inputs.

Xhcmaleorfemale[maleorfemale_Integer, h_Integer?Positive] /; 
   h > 2 && (maleorfemale == 0 || maleorfemale == 1) := 
  Which[(h < 3 || h > 7), 0, (h > 2 && h < 8), 
   Which[maleorfemale == 0, Xhcmale, maleorfemale == 1, 
     Xhcfemale][[h - 2]]];

More generally, since you have defined the maleorfemale input to Xhcmaleorfemale via a result of X, I think you would have more readable code if you used Boolean (True/False) values not zero and 1.

Finally, and this isn't a Mathematica-specific issue, I don't think it's good practice to create a variable that is 1 or True when male, and 0 or False when female, and then call it maleorfemale. Your code becomes less readable. It does matter how you name your variables. For more on this, I recently read The Art of Readable Code by Dustin Boswell and would recommend it even though it isn't specifically about Mathematica.

I would suggest that you instead have a variable isMale that takes a Boolean value. So your code would become the much simpler:

Xhcmaleorfemale[isMale : (True | False), h_Integer?Positive] /;  h > 2 := 
  Which[(h < 3 || h > 7), 0, (h > 2 && h < 8), 
   If[isMale, Xhcmale, Xhcfemale][[h - 2]]];

Notice the use of the single pipe |. This is for Alternatives in patterns, which is not the same as Or.

share|improve this answer
add comment

Not the answer you're looking for? Browse other questions tagged or ask your own question.