I've tried to write a simple function, which input is binary number in string format and converts binary to decimal. But in the output I always get the wrong thing: the 'res' value in line 3, no matter what the input is ('1010', '10010111010', etc.). Also, I've tried to debug the code and the function doesn't even start the loop, as if it wasn't there... So, I just don't see my mistake
def bin_to_dec(bin):
bin = bin[::-1]
res = 0
for i in range(len(bin)):
if bin[i] == 0:
res += 2**i
return res
You are comparing the string "0" to the number 0 and they are, trivially, unequal.
So, contrary to what you say, the loop is actually looping; but the if statement will never be true.
Of course, also, you should probably add when the number is 1, not when it's 0.
def bin_to_dec(bin):
bin = bin[::-1]
res = 0
for i in range(len(bin)):
if int(bin[i]) == 1:
res += 2**i
return res
Notice the addition of int().
if bin[i] == '1'
This will correct the problem. bin[i] is a character and you are comparing it to a number which always results in false.
You can just use the built in int function:
def binaryToDecimal(n):
return int(n,2)
Related
I'm trying to become comfortable with python. I've been trying some simple activities that I've given in my beginning c++ classes when I was teaching. I did one involving functions and writing a file which worked flawlessly. I thought this one would be easier. It acts like it is in a silent endless loop, but it won't even let me trace it. Can someone see where I am going awry?
# Find Adam Numbers
def isAdamNumber(candidate):
isAdam = False
rev = reverse(candidate)
square = candidate * candidate
revsq = rev*rev
if revsq == reverse(square):
isAdam = True
return isAdam
def reverse(num):
rev=0
while num > 0:
rev = rev * 10 + num%10
num/=10
return rev
for x in range (11,25):
if isAdamNumber(x):
print(x, " is an adam number\n")
The quick fix is to change /= with the integer division version, //=
Inside the reverse function, you are going into an infinite loop. num value always will be greater than 0, therefore the while loop will continuously run. In python, you can get the reverse of the function without much effort. Convert the integer to string and reverse the string and now change the string back to integer.
def reverse(num):
num_str = str(num)[::-1]
return int(num_str)
I think this function definition can solve your problem.
To visualize the python to learn and teach, use this link
The problem has already been addressed by the other answers, so here's the expanded and simplified version of the slicing that's going on [this doesn't actually use slicing]:
def reverse(num):
rev = ''
num = str(num)
for i in range(len(num) - 1, -1, -1):
rev += num[i]
return int(rev)
This counts backward from the last element in the string version of num, and adds all the elements of num (in reverse order) to rev.
num > 0 is never False. Dividing a positive number by 10 repeatedly makes it smaller, but it never becomes zero, so the while loop keeps repeating.
Use //= instead. It rounds to the nearest integer, so it will reach 0.
This also wouldn't reverse numbers (unless I'm missing something). Alternatively, you can use
int(str(num)[::-1])
which converts the number to a string, reverses it using slicing, and turns it back into an integer.
def toBinary(decimal, binaryList):
if decimal <= 1:
return binaryList
else:
decimal = decimal //2
return toBinary(decimal, binaryList)
binaryList.append(decimal %2)
The functions returns empty brackets instead of printing the binary number as a list.
Your code is on the right track but has issues. First is what #KlausD comments, no line directly after a return gets executed. So the order of statements is at issue. Next, the variable binaryList doesn't get initialized in your provided code fragment. It could get initialized by the caller:
array = toBinary(13, []):
which works, but the caller might find it strange. We could intialize it using a default:
def toBinary(13, binaryList=[]):
But as a container type, that would constitute a dangerous default which we want to steer clear of. We could safely initialize it to None as a default and reinitialize it later in the code:
def toBinary(decimal, binaryList=None):
# ...
if binaryList is None:
binaryList = []
Which is safe and hides this argument from the caller. Next, by dividing, we're analyzing our decimal digits from right to left, so we need to build up our binary number in the same direction, thus append():
binaryList.append(decimal % 2)
is a problem as it builds up the binary result from left to right. We could end with a revese() but it's probably better to use binaryList.insert(0, ...) to build in the proper direction. Finally, this is a special case:
array = toBinary(0)
as we're going to use a zero argument to trigger end of recursion but how it affects our result (i.e. not at all) is different than if we're passed zero from the get-go (i.e. return a [0]). Here's my rework of your code that addresses all of these issues:
def toBinary(decimal, binaryList=None):
if decimal == 0:
return binaryList or [0]
if binaryList is None:
binaryList = []
binaryList.insert(0, decimal % 2)
return toBinary(decimal // 2, binaryList)
print(toBinary(13))
OUTPUT
> python3 test.py
[1, 1, 0, 1]
>
It is better not to return binary list.
def toBinary(decimal, binaryList):
if decimal <= 0:
return
else:
toBinary(decimal//2, binaryList)
binaryList.append(decimal %2)
This code also converts to Binary. It can also convert into other bases. Just change the parameter base, to the base you want.
import string
def to_base(value, base=2): # converts decimal to base n
string_slice = string.printable[0:base]
data_dict = {}
for each_character, each_number in zip(string_slice, range(base)):
data_dict.update({each_character: each_number})
data = []
temporary_var = value
data.append(temporary_var)
while True:
temporary_var = temporary_var // base
data.append(temporary_var)
if temporary_var < base:
break
else:
continue
result = ''
for each_data in data:
result += list(data_dict.keys())[each_data % base]
result = result[::-1]
return result by
My code may not be perfect. Feel free to suggest improvements.
print(to_base(5, base=2)) # Outputs : 101. Because 101 is 5 in binary
print(to_base(17, base=16)) # Outputs : 11. Because 11 is 17 in hexadecimal
My teacher solved this question "Write a function which takes a n digits number as an input and return True if the biggest digit in this number is divisible by 3" like this:
def is_divisable(n):
a = str(n)
b = 0
for i in a:
if int(i)>b:
b = int(i)
if b % 3 == 0:
return "True"
print is_divisable(67479)
I have thought of it in another way but my code is not working and
I am getting an error says:
"TypeError: 'int' object is not iterable"
def is_dvo(n):
if max(n) % 3 == 0:
return True
print is_dvo(67479)
You don't quite say what your question is, but if you want another way to solve the problem,
def is_divisable(n):
return int(max(str(n))) % 3 == 0
This code converts the number to its decimal string representation, finds the largest digit (as a character), changes that digit to an integer, checks if that is divisible by 3, then returns that answer.
If your question is why you are getting that error, your parameter n is an integer, and you try to apply the max() function to that integer. However, max() is supposed to be used on iterable objects such as strings, lists, tuples, generators, and so on. My code changes the integer to a string before using max() so it does not have that problem, and it iterates over the digits in the string.
You can condense the code to a single line:
def is_divisable(n):
return max(map(int, str(n)))%3 == 0
Try:
max(str(n), key=int) in {'3', '6', '9'}
In other words, if I am presented with the number 54352, I want an expression that will tell me the width of that number is 5. I could use a for each loop to do this I know, but that seems rather cumbersome. Any other ideas?
you can use len(str(54352)) which will return 5 by converting it into a string, and returning the length of the string representation of the number.
Another way, a bit longer, would be:
def ilen(n):
i=0
while n != 0:
n /= 10
i += 1
return i
ilen(54352)
Actually is more like len(str(abs(n))) because -1 should probably have length 1.
Try
n = 54352
print (len(str(abs(n))))
Amended as user2722968 is correct.
I've just started exploring the wonders of programming. I'm trying to write a code to identify numeric palindromes. Just looking at numbers and not texts. I'm trying to learn to use recursion here. But I'm just not getting anywhere and I can't figure out what's wrong with it.
My idea was to check first string vs the last, then delete these two if they match, and repeat. Eventually there'll be nothing left (implying it is a palindrome) or there will be a couple that doesn't match (implying the reverse).
I know there are better codes to finding palindromes in but I just wanted to try my hand at recursion.
So what's wrong?
def f(n):
global li
li=list(str(n))
if (len(li)==(1 or 0)):
return True
elif li[len(li)-1]==li[0]:
del li[0]
del li[len(li)-1]
if len(li)==0:
return True
if len(li)>0:
global x
x=''.join(li)
str(x)
f(x)
else:
return False
Thanks in advance!
A few comments
Why are x and li globals? In recursion, all variables should be local.
Why are you converting back and forth between str and list? You can subscript both of them
You need to return the result of your recursive call: return f(x)
Try these suggestions, and see how it works out.
Before looking into it too much, if (len(li)==(1 or 0)): doesn't do what you're expecting it to do. (1 or 0) will always evaluate to 1.
You probably want:
if len(li) in (1, 0):
There are a couple of problems with your solution. Let me analyse them line by line.
You don't need global statements if you don't intend to change variables outside of function scope. Thus, I removed two lines with global from your code.
li=list(str(n)): casting a string to a list is unnecessary, as a string in Python has a similar interface to an immutable list. So a simple li = str(n) will suffice.
if (len(li)==(1 or 0)):: although it looks OK, it is in fact an incorrect way to compare a value to a few other values. The or operator returns the first "true" value from its left or right operand, so in this case it always returns 1. Instead, you can use the in operator, which checks whether the left operand is an element of a right operand. If we make the right operand a tuple (1, 0), all will be well. Furthermore, you don't need parentheses around the if statement. You should write: if len(li) in (1, 0):
elif li[len(li)-1]==li[0]: is fine, but we can write this shorter in Python, because it supports negative list indexing: elif li[-1] == li[0]:
Because we don't use lists (mutable sequences) because of point 2., we can't do del li[0] on them. And anyway, removing the first element of a list is very inefficient in Python (the whole list must be copied). From the very same reason, we can't do del li[len(li)-1]. Instead, we can use the "splicing" operator to extract a substring from the string: li = li[1:-1]
if len(li)==0: is unnecessary long. In Python, empty strings and lists resolve to False if tested by an if. So you can write if not li:
if len(li)>0:: You don't have to check again if li is not empty -- you checked it in point 6. So a simple else: would suffice. Or even better, remove this line completely and unindent the rest of the function, because the body of the if in 6. contains a return. So if we didn't enter the if, we are in the else without writing it at all.
x=''.join(li): We don't need to convert our string to a string, because of the decision made in 2. Remove this line.
str(x): This line didn't do anything useful in your code, because str() doesn't modify its argument in place, but returns a new value (so x = str(x) would have more sense). You can also remove it.
f(x): This is a valid way to call a recursive function in Python, but you have to do something with its value. Return it perhaps? We'll change it to: return f(li) (as we don't have an x variable any more).
We end up with the following code:
def f(n):
li = str(n)
if len(li) in (1, 0):
return True
elif li[-1] == li[0]:
li = li[1:-1]
if not li:
return True
return f(li)
else:
return False
It's almost what we need, but still a little refinement can be made. If you look at the lines if not li: return True, you'll see that they are not necessary. If we remove them, then f will be called with an empty string as the argument, len(li) will equal 0 and True will be returned anyway. So we'll go ahead and remove these lines:
def f(n):
li = str(n)
if len(li) in (1, 0):
return True
elif li[-1] == li[0]:
li = li[1:-1]
return f(li)
else:
return False
And that's it! Good luck on your way to becoming a successful programmer!
Split the whole show out into a list, then just:
def fun(yourList):
if yourList.pop(0) == yourList.pop(-1):
if len(yourList) < 2:
return True # We're a palindrome
else:
return fun(yourList)
else:
return False # We're not a palindrome
print "1234321"
print fun(list("1234321")) # True
print "6234321"
print fun(list("6234321")) # False
def palindrome(n):
return n == n[::-1]
It's hard to tell what you intend to do from your code, but I wrote a simpler (also recursive) example that might make it easier for you to understand:
def is_palindrome(num):
s = str(num)
if s[0] != s[-1]:
return False
elif not s[1:-1]:
return True
else:
return is_palindrome(int(s[1:-1]))
number = int(raw_input("Enter a number: "))
rev = 0
neg = number
original = number
if (number < 0):
number = number * -1
else:
number = number
while ( number > 0 ):
k = number % 10
number = number / 10
rev = k + ( rev * 10 )
if (number < 1):
break
if ( neg < 0 ):
rev = ( rev * -1)
else:
rev = (rev)
if ( rev == original):
print "The number you entered is a palindrome number"
else:
print "The number you entered is not a palindrome number"
This code even works for the negative numbers i am new to programming in case of any errors
dont mind.