0

Leet-Code 326. Power of Three:

Given an integer n, return true if it is a power of three. Otherwise, return false.

An integer n is a power of three, if there exists an integer x such that n == 3x.

Question link

My code

bool isPowerOfThree(int n) {
    if(n == 0)
        return false;
    double x = log(n)/log(3);
    if(x == ceil(x))
        return true;
    return false;
}

Why am I getting the wrong answer for n = 243?
I cout the both x and ceil(x) and both are equal.
Also when I do the log10 instead of log, it gets accepted but when I do the log2 instead of log, it failed again.

phuclv
  • 37,963
  • 15
  • 156
  • 475
  • 6
    Floating-point numbers like `double` are inherently imprecise - can you think of a solution that uses only integers, instead? – Wander Nauta May 28 '21 at 09:28
  • 3
    `log(243) / log(3)` is not precisely `5`. (It's in math but not in floating point arithmetic.) To prove this, try `std::log(243) / std::log(3) - 5`: [**Live Demo on coliru**](http://coliru.stacked-crooked.com/a/c59a71ec5686eaea). – Scheff's Cat May 28 '21 at 09:28
  • 1
    But when using log10 instead of log, I am getting the right answer and leetcode even accepted my code. – Hritik Kumar May 28 '21 at 09:33
  • 5
    Sometimes you win, and sometimes you lose... That doesn't change the rules of floating point arithmetic... ;-) – Scheff's Cat May 28 '21 at 09:34

2 Answers2

1

Floating-point arithmetic is designed to approximate real-number arithmetic. A binary-based floating-point format represents a finite number as some integer scaled by a power of two (with limits on the ranges of the integer and the power).

log(243) and log(3) have irrational values and so cannot be represented as an integer scaled by a power of two. The closest value to log(243) that is representable in the format commonly used for double (IEEE-754 binary64) is 5.49306144334054824440727315959520637989044189453125, which is 6,184,637,367,337,933•2−50. The closest value to log(3) that is representable is 1.0986122886681097821082175869378261268138885498046875, which is 4,947,709,893,870,347•2−52.

When these two numbers are divided in the double format, the result is 4.99999999999999911182158029987476766109466552734375. Obviously, that is not equal to its ceiling, 5, so your test routine returns false.

The rounding errors that occur in floating-point arithmetic vary, so using log10 instead of log may happen to get rounding errors in the log10 and the division that cancel, resulting in a computed quotient of 5. Also, the library functions like log are implemented with varying quality—they might not always return the closest representable value.

Generally, you should avoid using floating-point arithmetic for tests such as this. Redesign your code to use integer arithmetic.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
-1

An simple and accepted solution without using logarithm:

bool isPowerOfThree(int n) {
        if (n <= 0) return false;
        
        long int a = 1;
        
        while (a < n)
        {
            a *= 3;
        }
                
        return a == n;
    }

You should read the solution tab on LeetCode, there are a lot of interesting tips here. The Approach 3: Mathematics, common pitfalls section is about your problem.

Kapitany
  • 1,319
  • 1
  • 6
  • 10
  • Thanks but I did the same logic later on. What I am looking for is the fault where it has gone wrong in case of 2 or natural logarithm but not in case of common algorithm i.e., base 10. – Hritik Kumar May 28 '21 at 09:58
  • 1
    (a) Code without explanation is not a good answer. (b) The question is not just “How do I test whether a number is a power of three?” but specifically “Why am I getting the wrong answer for `n = 243`? This post does not answer that. – Eric Postpischil May 28 '21 at 11:14