3
$\begingroup$

I have the Following Matrixes;

 a[n_, m_] := BlockRandom[Table[RandomInteger[{1, 9}], {i, 1, n}, {j,1,m}]]
 b[n_, m_] := BlockRandom[Table[RandomInteger[{1, 9}], {m}]]

Where a[n,m] is a nxm Matrix and b[n,m] is a single row vector with length m. I want to divide a[n,m] by b[n,m]. So I had the following two options.

c1[n_, m_] := Transpose[Transpose[a[n, m]]/b[n, m]]
c2[n_, m_] := a[n, m]/Table[b[n, m], {n}]

they both give the output I want. The only problem is that I think it is too messy and too slow. Is there someone out there who can either give me a solution which is way faster, or one that is cleaner.

"To test it I used n == 1000 and m == 1000 and the following function"

Timing[Total[Total[c1[1000, 1000]]]]
Timing[Total[Total[c2[1000, 1000]]]]

{0.582971, 1304220271/840}

{0.902095, 1304220271/840}

If you came this far reading it through, thank you and hopefully you are willing to help.

$\endgroup$
1
$\begingroup$

Actually your first solution, c1, is faster than the 3 that I came up with to do this problem,

c1[n_, m_] := Transpose[Transpose[a[n, m]]/b[n, m]]
c2[n_, m_] := a[n, m]/Table[b[n, m], {n}]
c3[n_, m_] := #/b[n, m] & /@ a[n, m]
c4[n_, m_] := 1/b[n, m] # & /@ a[n, m]
c5[n_, m_] := (a[n, m]) ConstantArray[1/b[n, m], {n}]

RepeatedTiming[Total[Total[c1[1000, 1000]]]]
RepeatedTiming[Total[Total[c2[1000, 1000]]]]
RepeatedTiming[Total[Total[c3[1000, 1000]]]]
RepeatedTiming[Total[Total[c4[1000, 1000]]]]
RepeatedTiming[Total[Total[c5[1000, 1000]]]]
(* {0.413, 3811960843/2520} *)
(* {0.618, 3811960843/2520} *)
(* {0.662, 3811960843/2520} *)
(* {0.67, 3811960843/2520} *)
(* {0.413, 3811960843/2520} *)

You can make things considerably faster if you convert to real numbers instead of integers,

anum[n_, m_] := N@a[n, m];
bnum[n_, m_] := N@b[n, m];


c1num[n_, m_] := Transpose[Transpose[a[n, m]]/bnum[n, m]]
c2num[n_, m_] := anum[n, m]/Table[bnum[n, m], {n}]
c3num[n_, m_] := #/bnum[n, m] & /@ anum[n, m]
c4num[n_, m_] := 1/bnum[n, m] # & /@ anum[n, m]
c5num[n_, m_] := (anum[n, m]) ConstantArray[1/bnum[n, m], {n}]


RepeatedTiming[Total[Total[c1num[1000, 1000]]]]
RepeatedTiming[Total[Total[c2num[1000, 1000]]]]
RepeatedTiming[Total[Total[c3num[1000, 1000]]]]
RepeatedTiming[Total[Total[c4num[1000, 1000]]]]
RepeatedTiming[Total[Total[c5num[1000, 1000]]]]
(* {0.051, 1.51268*10^6} *)
(* {0.166, 1.51268*10^6} *)
(* {0.20, 1.51268*10^6} *)
(* {0.20, 1.51268*10^6} *)
(* {0.049, 1.51268*10^6} *)

Sometimes you can get a rational expression via Rationalize, but not always. I tried using Compile, but I couldn't get it any faster than c1num and c5num.

$\endgroup$
  • $\begingroup$ Thanks a lot! I see there are more ways to do it, but as you say the first one I had was already one of the fastest.Still, you tip of working with real numbers really helped me out!!! Sometimes finding such a simple solution can be very hard.. But why are more complex (longer) numbers faster than integers? $\endgroup$ – immaan Dec 7 '15 at 13:34
  • $\begingroup$ I don't know if floating point is always faster than integer, it seems that like you say for some operations it should be faster with less precision needed. But here you are summing large numbers of rational fractions. So at each step you need to find the lowest common denominator, add, then simplify. Much faster to add decimals. $\endgroup$ – Jason B. Dec 7 '15 at 13:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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