-7

Write a simple procedure, myLog(x, b), that computes the logarithm of a number x relative to a base b.n other words, myLog should return the largest power of b such that b to that power is still less than or equal to x.

x and b are both positive integers; b is an integer greater than or equal to 2. Your function should return an integer answer.

Do not use Python's log functions; instead, please use an iterative or recursive solution to this problem that uses simple arithmatic operators and conditional testing.

What is wrong in the below code? As they have not mentioned what to return when the condition fails, so had kept false

def myLog(x, b):
    count = 1

    while x > 0 and b >= 2:
        ans = b ** count
        if (ans == x):
            print str(count)
            break
        elif (ans > x):
            print str(count-1)
            break
        count += 1
    else:
        return False
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • What does it do that you weren't expecting? Also, I realize you're following an assignment, but the assignment is crazy; it's like asking you to build a car without using any wheels. – Dan Nov 12 '13 at 19:37
  • 2
    @Dan: Writing an integer log function is a reasonable thing to know how to do, and writing it in terms of a floating-point log function is not a good answer (if, say, you want it to work with numbers too big to fit into a float without loss of precision, or too big to fit at all). – abarnert Nov 12 '13 at 19:38
  • I answered this question twice yesterday, but it gets instantly downvoted and removed by author. – alko Nov 12 '13 at 19:40
  • One obvious problem with your code is that if it succeeds it returns `None`. `print` doesn't cause the function to return anything, it just prints a value. So you do that, then `break`, then fall off the end of the function. (Also, you almost never need to `print str(x)`, since `print` already calls `str` on its argument.) Just `return count` and `return count-1`. – abarnert Nov 12 '13 at 19:42
  • @Dan Integer log function is trivial lol. It only requires like 3rd/4th grade math. – Shashank Nov 12 '13 at 19:49
  • @ShashankGupta & abarnert: Your responses to my earlier comment are precisely my point. Reinventing things, especially trivial things, is a bad habit to get into as a programmer. The assignment "find an implementation of integer log that doesn't lose precision by converting to floating point; show your sources and build a working example" makes much more sense. No wheel reinvention, and the fact that abarnert has effectively done the assignment for the OP with his correct answer below would not be cheating in that case. – Dan Nov 13 '13 at 01:28
  • @Dan well in that case wouldnt this be more "reinventing the wheel" than "building a car without using any wheels"? This little function is hardly a "car". :P And I don't think it encourages reinventing things. For example I've been learning the C language where you basically have to reinvent everything thats already "invented" in C++. I still don't think it makes me a bad programmer because when I program in Python I abuse the hell out of library/built-in functions. In my University we had to reinvent parts of the STL in C++. Did that encourage me to reinvent things outside of coursework? No! – Shashank Nov 13 '13 at 02:05
  • If anything it just made me more thankful that the STL was there for me so I wouldn't have to design a queue/map data structure or whatever every time I wanted to solve a simple problem. In other words, the "reinventing the wheel" assignments just made me more appreciative of STL rather than encouraging me to not use it. – Shashank Nov 13 '13 at 02:07

2 Answers2

2

Since you haven't explained what problem you're trying to solve, all I can do is guess. But…

Your function never returns a number. If it succeeds, it prints out a number, then falls off the end of the function and returns None. If it fails, it returns False. And there's no other return anywhere in the code.

That's easy to fix: just return the value instead of print-ing it:

def myLog(x, b):
    count = 1

    while x > 0 and b >= 2:
        ans = b ** count
        if (ans == x):
            return count
        elif (ans > x):
            return count-1
        count += 1
    else:
        return False

You can improve performance by doing ans *= b each time through the loop instead of ans = b ** count. If the numbers are huge, dividing x by b might be better—division is usually slower than multiplication, but getting out of the huge-number domain early might help more than avoiding division.

It's also got some style problems, like the unnecessary parentheses some (but not all) of your conditions.

And finally, you may want to consider writing a "test driver". For example:

repcount = 100
errcount = 0
for _ in range(repcount):
    x = generate_nice_random_x()
    b = generate_random_base()
    log1, log2 = myLog(x, b), int(math.log(x, b))
    if log1 != log2:
        print('log({}, {}): {} != {}'.format(x, b, log1, log2))
        errcount += 1
print('{}/{} errors'.format(errcount, repcount))

Start with a small repcount to make sure you don't spam the screen; when you're happier with it, use a much larger one. Meanwhile, I'll leave it to you to figure out a good domain to choose from for testing log functions.

abarnert
  • 354,177
  • 51
  • 601
  • 671
0

This is a question on an exam, that is currently ongoing.MITx: 6.00.1x Introduction to Computer Science and Programming

diek
  • 657
  • 7
  • 16