3

I want to make a table to get a nbyn matrix. However, the diagonal are divided by zero. For example:

n = 5;
Table[1/(Sin[i] - Sin[j]), {i, 1., n}, {j, 1, n}]

I can use IF statement, however, is there any more elegant way to set diagonal elements to zero or any other default value?

One solution is, if the matrix is symmetric:

m = Table[0,{i,1,n},{j,1,n}];
Table[m[[i,j]] = 1/(Sin[i] - Sin[j]), {i, 1., n-1}, {j, i+1, n}]
Karsten7
  • 27,448
  • 5
  • 73
  • 134
MOON
  • 3,864
  • 23
  • 49

4 Answers4

6
Normal[SparseArray[{{i_, j_} /; j != i :> 1/(Sin[i] - Sin[j])}, {5, 
   5}]]

Non-zero diagonal, e.g. Pi:

Normal[SparseArray[{{i_,i_} -> Pi, {i_, j_} /; j != i :> 1/(Sin[i] - Sin[j])}, {5, 5}]]
Marius Ladegård Meyer
  • 6,805
  • 1
  • 17
  • 26
4

Update: Timings

ClearAll[f1, f2, f3, f4]
f1 = Block[{Power}, Power[0. | 0, -1] = #; 
    Table[1/(Sin[i] - Sin[j]), {i, 1, #2}, {j, 1, #2}]] &;
f2 = With[{v = #, n = #2}, Array[If[#1 == #2, v, 1/(Sin[#1] - Sin[#2])] &, 
      {n, n}]] &; (* Rashid's answer*)
f3 = SparseArray[{{i_, j_} /; j != i :> 
      1/(Sin[i] - Sin[j])}, {#2, #2}, #] &; (* a variant of Marius' answer *)
f4 = SparseArray[{{i_, i_} -> #, {i_, j_} /; j != i :> 
      1/(Sin[i] - Sin[j])}, {#2, #2}] &; (* Marius's answer *)

Equal @@ (#[Pi, 5] & /@ {f1, f2, f3, f4})

True

n = 300;
{HoldForm[#], First[AbsoluteTiming[#[Pi, n]]]} & /@ {f1, f2, f3, 
   f4} // Grid

Mathematica graphics

Original post:

Temporarily re-define Power[0,-1] as a:

Block[{Power}, Power[0.|0, -1] = a; Table[1/(Sin[i] - Sin[j]), {i, 1., 5}, {j, 1, 5}]]

Mathematica graphics

kglr
  • 394,356
  • 18
  • 477
  • 896
  • Thanks for the timing tests! That's a great idea. I'll definitely add that to my answers in the future. – Rashid May 24 '16 at 15:38
4

I would prefer to use Array over SparseArray or Table here, because this matrix isn't really sparse and you are indexing over consecutive integers.

For example, if you're okay with non-Ifconditional forms, I would use Array together with Piecewise as follows:

f[i_, j_] := Piecewise[{{0, i == j}, {1/(Sin[i] - Sin[j]), True}}];
m1 = Array[f, {5, 5}]

When there are only two cases though (e.g., i==j or i!=j), I would personally use an If statement together with Array like this one-liner:

m2 = Array[If[#1==#2, 0, 1/(Sin[#1] - Sin[#2])]&, {5, 5}]
Rashid
  • 1,523
  • 10
  • 18
0

This is a different approach, that seems to be very fast

n = 5;
u = Sin[Range[n]] // N;
(Join[1/(u[[#]] - u[[1;;# - 1]]), {a}, 1/(u[[#]] - u[[# + 1;;]])])& /@ Range[n]
Vito Vanin
  • 568
  • 2
  • 8