MATLAB: How o check if a number is a power of 3

remainder

I divided the log value of the number to log(3) and checked for the remainder of division to 1. But when I enter the value of 9 or 27 my remainder value does not give 0. Thank you

Best Answer

What you are trying to do is a good start. But you probably need to use a tolerance, as I show.
You can only test to see if the result is CLOSE to an integer. A log will be a floating point number, so it will not be exact. Never trust the least significant bits of ANY floating point computation. Well, unless you truly know what you are doing. Then you will know what you can and cannot trust.
R = log([3 9 27 81 131])/log(3)
R =
1 2 3 4 4.4376
The first 4 look like integers. But the result need not be exactly an integer.
round(R) - R
ans =
0 -4.4409e-16 -4.4409e-16 -8.8818e-16 -0.4376
The trick is to use a tolerance.
abs(round(R) - R) < 1e-15
ans =
1×5 logical array
1 1 1 1 0
If the difference from an integer is reasonably small, then the original value was a power of 3. Of course, you need to be careful. If I try, I can always get a test like that to slip up.
R = log(9.000000000000001)/log(3)
R =
2
Again, it looks like 2.
abs(round(R) - R) < 1e-15
ans =
logical
1
And the tolerance test did not get upset. It LOOKS like a power of 3. But is it EXACTLY so?
9.000000000000001 == 3^2
ans =
logical
0
So MATLAB can see that it is not exactly 9, so not exactly a power of 3.
If your goal is to test if a set of numbers are EXACTLY positive integer powers of 3, then there are ways you could do so.
P3 = 3 .^(0:33);
So P3 is the set of integers that are exactly representable in MATLAB as positive integer powers of 3.
ismember([1 3 9 9.0000000000001 27 131],P3)
ans =
1×6 logical array
1 1 1 0 1 0
We cannot go past 3^33 in a double either.
sym(3)^34
ans =
16677181699666569
sprintf('%0.55f',3^34)
ans =
'16677181699666568.0000000000000000000000000000000000000000000000000000000'
(uint64 can go as high as 3^40. But that may not be relevant to you.)
As well, negative powers of 3 are problematic, since we cannot represent 1/3 exactly as a double.
sprintf('%0.55f',1/3)
ans =
'0.3333333333333333148296162562473909929394721984863281250'
So that is as close as a double can achieve.