value = input("Enter the binary value to convert to a decimal number.")
prod = 0
power = 0
ans = 0
for i in range (int(value)):
prod = ((int(value[*right most digit here*])) * ((2**power)))
ans = prod + ans
prod = 0
power + 1
else:
print (ans)
I am trying to create a binary calculator.
I believe I have the power part of the equation working as it begins with 2 ^ 0, then 2 ^ 1 for the next digit and so on. But I am having trouble getting the first part of the equation, the right most digit of the value inputted.
So let's say, 0101 was inputted. I want 1 * ( 2 ^ 0 ) in the first loop, 0 * ( 2 ^ 1) in the second loop, and so on; right to left. So with how indexing works in Python, how can I reverse index it so [4] is in the first loop, then [3] in the second loop, and so on.
Thanks for help.
However there are better options available, i am assuming you are clearing your basics. Following can be the options:
Note : You should use len(value) instead of int(value) in the loop.
# 1. When starting the loop from 0 (i.e. i=0). you can use ( len(value) - i )th index.'
for i in range (len(value)):
prod = ((int(value[len(value) - i - 1])) * ((2**power)))
ans = prod + ans
prod = 0
power = power + 1
# 2. Python also supports negative indexing, So you may run a loop from -1 to -len(value).
for i in range (-1,-len(value) - 1,-1):
prod = ((int(value[i])) * ((2**power)))
ans = prod + ans
prod = 0
power = power + 1
# 3. You can reverse the whole string in your first step and then loop from 0 to len(value)-1.
value = reversed(value)
for i in range (len(value)):
prod = ((int(value[i])) * ((2**power)))
ans = prod + ans
prod = 0
power = power + 1
But there are some bugs in the code (or may be lack on information). This code works only for unsigned integers. If you want it to work on signed numbers as well, you have to take 2's complement into consideration.
Below is a very simple code that works with signed numbers too (in case needed):
#convert binary string into decimal value. Works on 2's complement.
def binToDecimal(s):
neg = False
if s[0] == '1':
s = twosComp(s)
neg = True
#compute the decimal value
val = reduce(lambda x,y : int(x)*2+1 if y=='1' else int(x)*2,'0'+s)
#negate the value if the first bit is 1
return -val if neg else val
#return the 2's complement string
def twosComp(s):
s = list(s[::-1])
#take 1's complement
s = ['1' if i=='0' else '0' for i in s]
#take 2's complement
for i in range(len(s)):
if s[i] == '0':
#no carry will be generated in this case, so we break it.
s[i] = '1'
break
else:
s[i]='0'
# return 2's complement string
return ''.join(map(str,s))[::-1]
value = input("Enter the binary value to convert to a decimal number.")
power = 0
ans = 0
for i in reversed(value):
prod = int(i) * (2**power)
ans = prod + ans
power += 1
else:
print(ans)
Improved your code while keeping it as close to your code as possible. Your for loop was creating a list of 1 to whatever the value we input, that's not what you should be doing. One way of doing is, treating your input as a string (which basically is a list that can be iterated through) reverse it so you go from right to left, then do your operation on it on each value. You were trying to get the index of the location of the value input right? Why? Python is beautiful where you most likely don't need to directly tell the index of something.
value = input("Enter the binary value to convert to a decimal number.")
prod = 0
power = 0
ans = 0
for i in range(int(len(value))-1):
prod = ((int(value[-1])) * ((2**power)))
ans = prod + ans
prod = 0
power + 1
else:
print (ans)
You were doing the range of the value and not the input len so we use len() to get the length of the string that was inputted. -1 is there because the length of a string can be 3 for input 001 but if indexing 3 would be out of bounds because indexing starts at 0 not 1
Note that in Python a negative index value is accepted. Negative index means starts from the end of the list and count backwards, so I think that was the answer you were looking for.
For example if we have the list my_list=['a','b','c'] and we call my_list[-2] it will return 'b'
You have some mistakes in your code, so replace it with this:
value = input("Enter the binary value to convert to a decimal number: ")
value = int(value) # conversion from string to number
power = 0
ans = 0
while(value > 0):
lastDigit = value % 10 # last digit
value = value // 10 # cutting off last digit (for next iteration)
prod = lastDigit * (2 ** power)
ans = prod + ans
power = power + 1
print (ans)
Last digit is calculated as the remainder after division by 10 (value % 10)
and is cutting of by integer division by 10 (value // 10) - as in first grades of basic school: 27 % 10 = 7 27 // 10 = 2
Simpler way to achieve this with be to mention base as 2 with int(). For example:
>>> num = '110'
>>> int(num, 2)
6
In case you are looking for custom solution, you may create a function as:
def binary_string_to_int(binary_string):
int_num = 0
for i in binary_string:
int_num += int(i)
int_num *= 2
return int_num / 2
Sample run:
>>> binary_string_to_int('111')
7
>>> binary_string_to_int('101')
5
Related
I am writing code to solve the following codewars question: https://www.codewars.com/kata/5f79b90c5acfd3003364a337/train/python
My idea is to take all the integers from 1 to n, and take the last digit of each of these integers (bar 0), multiply them together, and return the 'last' non-zero digit of the result:
def last_digit(n):
factorials = []
factorials_n = 1
for i in range(1,n + 1):
i = str(i)
i = i[::-1]
for j in i:
if j == "0":
break
factorials.append(j)
break
# at this point factorials contains the first non-zero integers of each integer in reverse
for i in factorials:
factorials_n = factorials_n * int(i)
factorials_n = str(factorials_n)
factorials_n = factorials_n[::-1]
for i in factorials_n:
if i != "0":
return int(i)
The code passes a number of tests, but fails for 387 (returns 6, should be 2) and 1673 (returns 2 should be 4). I've tried doing print statements as debug but the code seems fine, perhaps it's the logic that fails at some point- any ideas?
The problem here is with the logic. Since you are dropping all the cases where the number ends in 0, we do not arrive at the correct answer.
Consider 2 x 8 x 30. To get the last digit of the factorial, multiplying last digits would suffice, but to find the last non zero digit, you have to evaluate 2 x 8 x 3
instead.
Using this solution as a reference, here's what you can do:
def last_digit(n):
# factorials = []
# factorials_n = 1
last = 1
d2 = 0
for i in range(1,n + 1):
ii = i
print(ii)
while(ii%2==0):
d2 +=1
ii = ii/2
while(ii%5==0):
d2 -=1
ii = ii/5
print(d2)
last = (last * ii)%10
print(last)
for i in range(0,d2):
last = (last *2)%10
return int(last)
Your code passes the test cases for numbers uptill 24, it fails when the non-zero digit from 25! gives an incorrect answer which get propogated forward for the numbers after it.
And also we can simply use the modulo operator to get the very last digit instead of converting it into a string
Example: 1234 % 10 equals 4 (which is the last digit)
My solution:
def last_digit(n):
factorial = 1
for i in range(1, n + 1):
# compute the factorial
prod = factorial * i
# keep dividing the product by 10 until the last digit is a !0 digit
while prod % 10 == 0:
prod = prod // 10
# only store the last 3 digits of the computed product.
# You can keep more digits to get accurate results for
# when the numbers are higher than 10000
factorial = prod % 1000
# return the last digit
return factorial % 10
As i said earlier, when the last !0 digit from 24! (6) is multiplied with 25, it outputs 150 which after removing the 0 gives 5 but it instead should be 4. Hence, in order to solve this we keep at least the last 3 digits instead of only the last digit.
Example: 6 * 25 = 150 => 5 (last !0 digit)
936 * 25 = 23400 => 4 (last !0 digit)
PS: !0 = non-zero
While practicing recursion I came across a question to reverse an integer using recursion. I tried to do the question without converting the integer into a string.
I was able to solve the question partially but the output would always come without any of the zeroes from the original input. Below is the code I came up with:
def reverseNumber(n):
if (n//10) == 0:
return n
lastDigit = n%10
ans = reverseNumber(n//10)
nod = 0
for i in str(ans):
nod += 1
return (10**nod)*lastDigit + ans
Upon inspection I could see that this was happening because when lastDigit is 0 it only returned the reversed integer from the recursive call i.e input 4230 will give 324.
But this also meant that all zeroes between the original input would also get removed as we went deeper in the recursive calls.
So please tell me how to modify this code so that zeroes in the original input are not removed while reversing.
You probably need just this:
def rev(n):
if n>0:
return str(n%10)+rev(n//10)
else:
return ''
reverseNumber should return an int and accept positive and negative numbers.
The simplest way to fix your code, without handling negative numbers, is:
def reverseNumber(n):
if n == 0:
return 0
lastDigit = n%10
n //= 10
return int(str(lastDigit) + str(reverseNumber(n))) if n else lastDigit
for test in (0, 123, 120):
print(test, reverseNumber(test))
Prints:
0 0
123 321
120 21
Yes! The reverse of 120 is 21 when you are dealing with int types as opposed to str types.
Another implementation that does handle negative numbers takes a whole different approach:
I have broken this out into two functions. Function rev is a generator function that assumes that it is being called with a positive, non-negative number and will recursively yield successive digits of the number in reverse. reverseNumber will join these numbers, convert to an int, adjust the sign and return the final result.
def reverseNumber(n):
def rev(n):
assert n >= 0
yield str(n % 10)
n //= 10
if n != 0:
yield from rev(n)
if n == 0: return 0 # special case
x = int(''.join(rev(abs(n))))
return x if n >= 0 else -x
tests = [0, 132, -132, 120]
for test in tests:
print(test, reverseNumber(test))
Prints:
0 0
132 231
-132 -231
120 21
For all non-negative n, when n < 10 it is a single digit and already the same as its reverse -
def reverse(n = 0):
if n < 10:
return str(n)
else
return str(n%10) + rev(n//10)
you can also try the following Python3 code. It will cover positive and negative integers to be reversed as integers - not as strings ...
x = int(input("What integer shall be reversed? "))
n = abs(x) # ... to handle negative integers
r = 0 # ... will hold the reversed int.
while n > 0: # Recursion part reversing int.
r = (r * 10) + (n % 10) # using '%' modulo
n = int(n / 10) # and a 'dirty way' to floor
if x < 0: # Turn result neg. if x was neg.
return (r * -1)
else:
return r # Keep result pos. if x was pos.
This approach will leave your zeros in the middle of the integer intact, though it will make any zero at the end of the initial number vanish - rightfully so as integers do not start with a zero. ;))
x = int(input('num: '))
result = 0
power = -1
while x != 0:
digit = x % 10
digit = digit**2
if digit > 9:
power += 2
else:
power += 1
result = result + digit * (10**power)
x //= 10
print(result)
Basically, I want to square every digit in an integer. For example, 984 should be 816416 or 405 should be 16025.
The interesting thing is that if I write result = result + digit * (10**power) on the eighth line and make the power = 0, then I get the correct result. However, it sounds illogical to me because I think that we should first decide whether digit > 9 or not. I mean, writing result = result + digit * (10**power) before the if statement is weird to me. So, could the code I shared work by editing some parts in this form? If not, could you explain why I should write it on the eighth line?, thanks.
Here the problem is that you are squaring your digit variable before the if condition which will fail if your digit is any value less than 10. For example, for just number 4, your value of digit variable will be 16 and thus power will be 1 and your result would be 160 then.
And you need to have it at the eight line before the if statement because, the if statements determine your power variable and your value wont shift and add to the result variable instead. For example - for 45 you would want the output to be 1625, but if you call the statement before the if condition, the power will be 0 and thus you will get a result of 185(25+160) instead of 1625.
x = int(input('num: '))
result = 0
power = 0
while x != 0:
digit = x % 10
digit2 = digit**2
result = result + digit2 * (10**power)
if digit2 > 9:
power += 2
else:
power += 1
x //= 10
print(result)
This should work.
Alternatively, you can directly manipulate the nature of input number is indeed a string, which you can start working on:
>>> squares = [int(x)*int(x) for x in input('Enter a number: ')]
Enter a number: 984
>>> squares
[81, 64, 16]
>>> result = int(''.join(map(str, squares)))
>>> result
816416
I need to sum 2 binary numbers (max len 8 and min 1) using only selective structures (if, elif, else) and loops (for, while).
You need to know in the binary sum:
0 + 1 = 1
1 + 0 = 1
1 + 1 = 0 (with carry 1)
The result must be the sum of these two numbers.
Also, show the partial results that are generated by adding two digits and carrying
I know you could easily do this, but the idea is use only selective structure and loops.
a = input("first binary: ")
b = input("second binary: ")
c = bin(int(a,2) + int(b,2))
OUTPUT example:
sum:
11001011
10001011
=========
101010110
Partial results:
digit = 0 Carry = 1
digit = 1 Carry = 1
digit = 1 Carry = 0
digit = 0 Carry = 1
digit = 1 Carry = 0
digit = 0 Carry = 0
digit = 1 Carry = 0
digit = 0 Carry = 1
This question is different to the others made, because none of the others answer just using selective and repetitive structures
If you are allowed to use slicing, you can do this:
num1 = '11001011' # you can replace these with input() calls
num2 = '10001011'
# reverse the strings as we will be doing the operations from the left, otherwise you will need to pass reversed strings in the for loop iterator
num1 = num1[::-1]
num2 = num2[::-1]
# to tackle uneven lengths you can pad with 0s
if len(num2)>len(num1):
padding = len(num2) - len(num1)
num1 = num1 + '0'*padding
else:
padding = len(num2) - len(num1)
num1 = num1 + '0'*padding
currentresult = ''
nextdigit = 0
# iterate over two numbers
for i, j in zip(num1,num2): # if you are not allowed to use zip, you can use two nested loops one for num1 and one for num2, and add an if condition to do the operations only when i == j
i = int(i) + nextdigit
if int(i) + int(j) == 3:
# case where current bits are 1 and 1, and carry from the last addition is 1
carry = 1
digit = 1
elif int(i)+int(j) == 2:
carry = 1
digit = 0
elif int(i)+int(j) == 1:
carry = 0
digit = 1
else:
carry = 0
digit = 0
currentresult += str(digit)
nextdigit = carry
# add next digit (if in case the carry from the last bits are 1)
if nextdigit == 1:
currentresult += str(nextdigit)
# reverse the strings as we got the result in reverse
finalresult = currentresult[::-1]
print(finalresult)
I am currently trying to use the luhn method to determine whether a credit card is valid or not in python and here is what I have so far:
print('What is your Credit Card number? :) (please put a space between each number)')
a = [int(x) for x in input().split()]
lengthy = len(a)
print(lengthy)
a.reverse()
print(a)
listx2 = []
listx1 = []
for x in range(len(a)):
modulus = x % 2
print(x, a[x])
if modulus != 0:
listx2.append(a[x]*2)
else:
listx1.append(a[x])
print(listx2)
print(listx1)
I don't know how to do the next step which is getting the sum of all of the digits of the numbers multiplied by two.(listx2) I have looked at different programs with the luhn method but I just can't seem to pick that part out. Thanks!
This is my interpretation of the Luhn algo.
def luhn(sequence):
digits = [int(digit) for digit in str(sequence)] # converts a full string of nums to a list comp of individual numbers
odd = digits[-1::-2] # string stepping (-1) indicates last item in list (-2) means to travel back another 2
even = digits[-2::-2]
checksum = 0
checksum += sum(odd)
evenmod = []
for digit in even:
if digit * 2 > 9:
digit = digit * 2
digit = int(str(digit)[0]) + int(str(digit)[1])
else:digit = digit * 2
evenmod.append(digit)
checksum += sum(evenmod)
if checksum % 10 == 0:
return True
else:
return False
print luhn(378282246310005)
print luhn(111111111111111)
print luhn(4751290083628479)
print luhn(5573485043994670)
Separate the even and the odd indeces to separate lists, then use a for statement to loop through the list, multiplying the list entries by two.
Notice the if statement that catches the issue with (e.g) 8 * 2 = 16.
Use sum:
summed_x2 = sum(listx2)