1
$\begingroup$

I am trying to find a code that will output the prime factor decomposition of a number but for some reason I keep getting error messages. It is supposed to output the exponent of 2 and the odd factor. So for 528 it would output 2^4 x 33. Any ideas?

prime[x_] := Module[{a, i, y},
            a = x/2;
            i = 0

                If[IntegerQ[x] == False, Print["Input integer."];
                    Return[]]

                While[IntegerQ[x] == True,
                    x = x/2;
                    i = i + 1;
                    ];

            y = x/2^i;

            Return[{i, y}]
  ]
$\endgroup$
  • $\begingroup$ Welcome to Mathematica.SE! I suggest the following: 1) As you receive help, try to give it too, by answering questions in your area of expertise. 2) Take the tour! 3) When you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. Also, please remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign! $\endgroup$ – Michael E2 Sep 27 '15 at 23:11
10
$\begingroup$

There are several problems with your code.

  • The first one is that you are missing a couple of semicolons to suppress output and delineate substatements in a compound function.

  • The second problem is that you are trying to assign a new value to x within the function definition. This doesn't work. x already has the value of whatever number you give. You need to have a local variable inside the Module that starts off having the value of the passed parameter, x.

Fixing these two things gives

prime[x_] := 
 Module[{a, i, y, xx = x}, a = x/2; i = 0 ; 
  If[IntegerQ[x] == False, Print["Input integer."]; Return[]]; 
  While[IntegerQ[xx] == True, xx = xx/2; i = i + 1;]; y = xx/2^i; 
  Return[{i, y}]]

This gets rid of the error message (which it would have been helpful to have provided), and outputs an answer that is (I think) what you want.

I'd like to make some other suggestions to make your code simpler and more "Mathematica-like". Firstly, you can assign the initial values of your local variables a and i in the first argument of Module. This simplifies the complexity of your code.

You could also remove the If statement by using the pattern-matching functionality of Mathematica so that your function only operates for integer inputs. Finally, you don't actually need that final Return. You would then have:

prime[x_Integer] := 
 Module[{a = x/2, i = 0, y, xx = x}, 
  While[IntegerQ[xx] == True, xx = xx/2; i = i + 1;]; 
  y = xx/2^i; {i, y}]

This gives the same output, at least for the couple of values I tried.

You could then define a different version of the function for non-integer input, like this:

prime::notint = "`1` is not an integer. Please provide integer input";

prime[x_] := Message[prime::notint, x]

So if you write:

prime[4.1]

You get a helpful error message.

prime::notint: 4.1 is not an integer. Please provide integer input

$\endgroup$
  • 1
    $\begingroup$ I was just posting the answer but you beated me with a wonderful one; thumbs up! $\endgroup$ – Raymond Ghaffarian Shirazi Sep 27 '15 at 23:19
  • $\begingroup$ Thank you for the suggestions, I have implemented them and fixed some of the small issues; however, I am getting {5,33/64} when I use the function for the number 528 when it should be {4,33}, for 2^4 x 33. Any ideas on how this can be solved? Also, I am using mathematica 9 if that makes any difference. $\endgroup$ – JanetHorne Sep 27 '15 at 23:36
  • $\begingroup$ I think I know why it is happening but not sure how to fix it. Because the beginning of the loop tests for integers only, when it gets down to 33, it is still an integer so the code still runs, however, I only want integers that are divisible by two. $\endgroup$ – JanetHorne Sep 27 '15 at 23:52
  • $\begingroup$ Ah, in that case you need EvenQ not IntegerQ. But this is a separate issue, so please don't edit your question or post a new one for that - a separate question would be closed as "easily found in the documentation". $\endgroup$ – Verbeia Sep 27 '15 at 23:56
5
$\begingroup$

Try this, just to get you started. Function arguments can't be modified in the module so I've used x0 to allow your code to run.

prime[x0_] := Module[{a, i, y, x},
  x = x0;
  a = x/2;
  i = 0 ;
  If[IntegerQ[x] == False, Print["Input integer."];
   Return[]];
   While[IntegerQ[x] == True,
   x = x/2;
   i = i + 1;
   ];
  y = x/2^i;
  Return[{i, y}]]
$\endgroup$
3
$\begingroup$
CenterDot @@ (Superscript @@@ FactorInteger[528])

$2^4\cdot 3^1\cdot 11^1$

Or... if you don't like exponents of "1":

CenterDot @@ (If[#[[2]] != 1, 
     Superscript[#[[1]], #[[2]]], #[[1]]] & ) /@ FactorInteger[528]

$2^4\cdot 3\cdot 11$

$\endgroup$
  • $\begingroup$ I prefer CenterDot @@ Superscript @@@ (FactorInteger[528] /. {a_, 1} :> a) for the last bit, myself. $\endgroup$ – Patrick Stevens Sep 28 '15 at 7:00
2
$\begingroup$

Personally I think the neatest way is:

powerOf2[x_Integer] := powerOf2[x/2] + {1, 0}
powerOf2[x_] := {-1, 2 x}

powerOf2[528]
$\endgroup$
2
$\begingroup$

You could use the built-in function IntegerExponent as follows.

EvenOddFactorsOf[n_?OddQ] := {{0, n}, Apply[CenterDot, {Superscript[2, 0], n}]}

EvenOddFactorsOf[n_] :=
   With[{e = IntegerExponent[n, 2]},
        {{e, n/2^e}, Apply[CenterDot, {Superscript[2, e], n/2^e}]}]

The function returns two formats. The first is a list of the exponent of 2 and the odd remainder, the second writes $2^e\cdot m$, where $m$ is the odd part of the input $n$.

$\endgroup$

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.