How to describe the maths behind this function - python

This is a Decimal to Binary converter. I need help explaining the math behind is as I don't have a clue how to explain all the Shifts etc.
number = int(raw_input("Enter the Number:"))
binary = ''
while number > 0:
binary = str(number % 2) + binary
number >>=1
print(binary)

The loop builds up a string which represents a binary value.
str(number % 2) finds the lowest bit of the number (either 0 or 1).
binary = str(number % 2) + binary adds the bit to the left end of string binary
number >>=1 removes the low bit now that we're done with it
while number > 0 continues until the number is 0

Suppose you are converting 56 to binary.
When right shift by 1 bit, 56 (111000) becomes 28(011100)
Note: The right shift operator causes the bit pattern in the first operand to be shifted right the number of bits specified by the second operand. Bits vacated by the shift operation are zero-filled for unsigned quantities
Like this, the variable, number is right shifted by 1 till it is greater than 1 and every time, the remainder of number divided by 2 (this will be 0 or 1 always) is appended to the result variable, binary
Finally, the variable binary will have the binary equvalent

Related

Python binary manipulation

I am manipulating binary values with python. Here is my statement:
I have a float value, for example: 127.136.
First, I split this value in order to differenciate the integer and the fractional values, then I transform them into bytes:
velocity = 127.136
split_num = str(velocity).split('.')
int_part = int(split_num[0]) # = 127
decimal_part = int(split_num[2]) # = 136
int_part_b = "{0:b}".format(int_part)
decimal_part_b = "{0:b}".format(decimal_part)
I have to send the final value as a 2 bits word.
The total space is 32 bits. 127 is the integer part and 136 is the fractional part. The integer part takes 16 bits and the decimal part takes 16 bits.
So I want to initialize 3 binary word of 32 bits like that:
final_value = 00000000000000000000000000000000
integer_value = 00000000000000000000000000000000
fractional_value = 00000000000000000000000000000000
But then how can I add the value of int_part_b from the 16th bits of integer_value so for example if int_part_b = 10011 I would like to have: integer_value = 00000000000100110000000000000000 and for the fractional one if decimal_part_b = 11110 I would like to have: fractional_value = 00000000000000000000000000011110
And at the end, I sum this two bits values to obtain:
final_value = 00000000000100110000000000011110
Does anyone has any idea about how to do that?
For this encoding to make any sense, the value in the fractional part should be a faction of 2^16 (or any denominator <= 65536 you pick as a convention).
You cannot obtain the fractional part of the float value by string manipulation because that makes you lose the base10 denominator. (e.g. 0.36 and 0.036 are two different fractions but your code will produce 36 in both cases).
Note that there are a lot of different ways to encode numbers in binary (BCD for example) so you probably should be specific on that in your question
Binary encoding:
Here is one way to do it with a denominator of 2^16:
velocity = 127.136
denom = 2**16
intPart,fracPart = divmod(round(velocity*denom),denom)
encoded = (intPart<<16) | fracPart
print(f"{encoded:032b}")
# 00000000011111110010001011010001
Or, more straightforwardly (but only if denom is 2**16):
encoded = round(velocity*2**16)
print(f"{encoded:032b}")
# 00000000011111110010001011010001
Here, the value in the right part (fractional) is 8913, representing a fraction of 8913/65536 (0.1360015...) which is as close to 0.136 as a binary fraction over 16 bits can get.
Decoding the value:
int(encoded[:16],2) + int(encoded[16:],2)/denom
# 127.13600158691406
Decimal encoding:
If you want to represent the fractional part in base 10, you'll have to decide on a base10 denominator that fits within 16 bits (e.g. 10000) and compute your fractional part accordingly.
velocity = 127.136
denom = 10000
intPart,fracPart = divmod(round(velocity*denom),denom)
encoded = (intPart<<16) | fracPart
print(f"{encoded:032b}")
# 00000000011111110000010101010000
Now the fractional part is 1360 representing a fraction of 1360/10000 (0.136) which doesn't lose precision compared to the base 10 original (as long as there are no more than 4 decimal digits)
Decoding the value:
int(encoded[:16],2) + int(encoded[16:],2)/denom
# 127.136
You don't really need 3 differend words, just use the binary shift operator and sum the integer and decimal parts like this:
final_value = (int_part << 16) + decimal_part
print("{:032b}".format(final_value))
So here you shift your integer part 16 bits to the left and then you add your decimal part to it so they will occupy there respective 16-bit words of the 32-bit word.

How does python handle very small float numbers?

This is more a curiosity than a technical problem.
I'm trying to better understand how floating point numbers are handled in Python. In particular, I'm curious about the number returned by sys.float_info.epsilon = 2.220446049250313e-16.
I can see, looking up on the documentation on Double-precision floating-point, that this number can also be written as 1/pow(2, 52). So far, so good.
I decided to write a small python script (see below. Disclaimer: this code is ugly and can burn your eyes) which start from eps = 0.1 and makes the comparison 1.0 == 1.0 + eps. If False, it means eps is big enough to make a difference. Then I try to find a smaller number by subtracting 1 from the last digit and adding the digit 1 to the right of the last and looking for False again by incrementing the last digit.
I am pretty confident that the code is ok because at certain point (32 decimal places) I get eps = 0.00000000000000011102230246251567 = 1.1102230246251567e-16 which is very close to 1/pow(2, 53) = 1.1102230246251565e-16 (last digit differs by 2).
I thought the code would no produce sensible numbers after that. However, the script kept working, always zeroing in a more accurate decimal number until it reached 107 decimal places. Beyond that, the code did not find a False to the test. I got very intrigued with that result and could not wrap my head around it.
Does this 107 decimal places float number have any meaning? If positive, what is it particular about it?
If not, what is python doing past the 32 decimal places eps? Surely there is some algorithm python is cranking to get to the 107 long float.
The script.
total = 520 # hard-coded after try-and-error max number of iterations.
dig = [1]
n = 1
for t in range(total):
eps = '0.'+''.join(str(x) for x in dig)
if(1.0 == 1.0 + float(eps)):
if dig[-1] == 9:
print(eps, n)
n += 1
dig.append(1)
else:
dig[-1] += 1
else:
print(eps, n)
n += 1
dig[-1] -= 1
dig.append(1)
The output (part of it). Values are the eps and the number of decimal places
0.1 1
0.01 2
(...)
0.000000000000001 15
0.0000000000000002 16
0.00000000000000012 17
0.000000000000000112 18
0.0000000000000001111 19
0.00000000000000011103 20
(...)
0.0000000000000001110223024625157 31
0.00000000000000011102230246251567 32
0.000000000000000111022302462515667 33
(...)
0.000000000000000111022302462515666368314810887391490808258832543534838643850548578484449535608291625976563 105
0.0000000000000001110223024625156663683148108873914908082588325435348386438505485784844495356082916259765626 106
0.00000000000000011102230246251566636831481088739149080825883254353483864385054857848444953560829162597656251 107
I ran this code in Python 3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:20:19) [MSC v.1925 32 bit (Intel)] on win32.
Your test involves a double rounding and is finding the number 2−53+2−105.
Many Python implementations use the IEEE-754 binary64 format. (This is not required by the Python documentation.) In this format, the significand (fraction portion) of a floating-point number has 53 bits. (52 are encoded in a primary significand field. 1 is encoded via the exponent field.) For numbers in the interval [1, 2), the significand is scaled (by the exponent portion of the floating-point representation) so that its leading bit corresponds to a value of 1 (20). This means is trailing bit corresponds to a value of 2−52.
Thus, the difference between 1 and the next number representable in this format is 2−52—that is the smallest change that can be made in the number, by increasing the low bit.
Now, suppose x contains 1. If we add 2−52 to it, we will of course get 1+2−52, since that result is representable. What happens if we add something slightly smaller, say ¾•2−52? In this case, the real-number result, 1+¾•2−52, is not representable. It must be rounded to a representable number. The common default rounding method is to round to the nearest representable number. In this case, that is 1+2−52.
Thus, adding to 1 some numbers smaller than 2−52 still produces 1+2−52. What is the smallest number we can add to 1 and get this result?
In case of ties, where the real-number result is exactly halfway between two representable numbers, the common default rounding method uses the one with the even low bit. So, with a choice between 1 (trailing bit 0) and 1+2−52 (trailing bit 1), it chooses 1. That means if we add ½•2−52 to 1, it will produce 1.
If we add any number greater than ½•2−52 to 1, there will be no tie; the real-number result will be nearer to 1+2−52, and that will be the result.
The next question is what is the smallest number greater than ½•2−52 (2−53) that we can add to 1? If the number has to be in the IEEE-754 binary64 format, it is limited by its significand. With the leading bit scaled to represent 2−53, the trailing bit represents 2−53−52 = 2−105.
Therefore, 2−53+2−105 is the smallest binary64 value we can add to 1 to get 1+2−52.
As your program tests values, it works with a decimal numeral. That decimal numeral is converted to the floating-point format and then added to 1. So it is finding the smallest number in the floating-point format that produces a sum greater than 1, and that is the number described above, 2−53+2−105. Its value in decimal is 1.110223024625156663683148108873914908082588325435348386438505485784844495356082916259765625•10−16.

Converting a calculated decimal number into 8 bit binary

I am currently making a python program that is byte adder related, it will prompt the user to enter 2 integers, add them together and if it's within the range of the actual size of a byte (0 to 255) display that number and also give the corresponding value in its 8 bit binary form, for example, the calculation is equal to 1, show the binary number which python declares as the correct one.
This is the task that I am doing ~
"The program must check the input data for the data type permitted and the data value limitations (the value of the integer must not exceed the actual size of byte-coded integers, i.e. min 00000000 and max 11111111 in Base 2 or min 0 and max 255 in Base 10 for positive integers" Input in both binary and decimal format with conversion to binary
def add():
Num1 = int(input("Input the first number between 0 and 255, the calculated answer must not be above 255: "))
Num2 = int(input("Input the second number between 0 and 255, the calculated answer must not be above 255: "))
calculatedanswer = Num1+Num2
if calculatedanswer >= 0 and calculatedanswer <=255:
print("The answer in decimal is" ,calculatedanswer,)
**bin(calculatedanswer)**
elif calculatedanswer < 0 and calculatedanswer >255:
print("Please ensure the added numbers are above 0 and below 255")
add()
This is my code so far, I have no trouble getting it to display the standard decimal number, but I really can't get the bin(calculatedanswer) to show the binary equivalent of it. I tried using this method that I found on YouTube.
I think my main problem here is my lack of understanding of how "bin" works on python as this is really the first time I am using it.
I have put asterisks around the line that I am having trouble with.
You do have to print the value:
>>> print(bin(160)) # This version gives the 0b prefix for binary numbers.
0b10100000
>>> print(format(160,'08b')) # This specifies leading 0, 8 digits, binary.
10100000
>>> print('{:08b}'.format(160)) # Another way to format.
10100000
>>> print(f'{160:08b}') # Python 3.6+ new f-string format.
10100000
One option for printing it would be to slice off the 0b portion of the result, which I assume is what you mean when you say you are having problems with the bin function.
Try this:
print(bin(calculatedanswer)[2:]))

Converting Binary to Decimal in python (without built in binary function)

Alrighty, first post here, so please forgive and ignore if the question is not workable;
Background:
I'm in computer science 160. I haven't taken any computer related classes since high school, so joining this class was a big shift for me. It all seemed very advanced. We have been working in Python and each week we are prompted to write a program.
I have been working with this problem for over a week and am having a hard time even starting.
The prompt is to read an integer containing only 1's and 0's,
process the binary number digit by digit and report the decimal equivalent. Now, I have gotten some tips from a classmate and it sent me at least in a direction.
Set up a couple of counters;
using the % operator to check the remainder of the number divided by 2, and slicing off the last number (to the right) to move on to and process the next digit.
I am having an incredibly hard time wrapping my head around what formula to use on the binary digits themselves which will convert the number to decimal.
setbitval = 0
counter = 0
user = int(input("enter a binary value. "))
if user % 2 == 1:
user = (user/10) - .1
setbitval += 1
This is all I've got so far.. My thinking is getting in the way. I've searched and searched, even through these forums.
Any information or thoughts are extremely appreciated,
T
Edit: okay guys, everyone's help has been extremely useful but I'm having a problem checking if the user input is not a binary number.
for i in reversed(bits):
decimal += 2**counter * int(i)
counter += 1
This is the formula someone here gave me and I've been trying different iterations of "for i in bits: if i in bits: != 0 or 1" and also "if i in bits: >= 1 or <=0".
Any thoughts?
you can use this code:
binary= raw_input("Binary: ")
d= int(binary, 2)
print d
To convert binary value to decimal you need to do the following:
Take the least significant bit and multiply it by 2^0, then take the next least significant beat and multiply it by 2^1, next one by 2^2 and so on...
Let's say, for example you need to convert a number 1010 to decimal:
You would have 0*2^0 + 1*2^1 + 0*2^2 + 1*2^3 = 0 + 2 + 0 + 8 = 10
So in your python code, you need to:
read the int that the user inputted (representing the binary value).
convert that int and convert it to string, so you can break it into list of digits
make a list of digits from the string you created (a list int python can be created from a string not an int, that's why you need the conversion to string first)
go trough that list of bits in reverse and multiply every bit by 2^k, k being the counter starting from 0
Here's the code that demonstrates what I just tried to explain:
user_input = int(input("enter a binary value"))
bits = list(str(user_input))
decimal = 0
counter = 0
for i in reversed(bits):
decimal += 2**counter * int(i)
counter+=1
print 'The decimal value is: ', decimal
I'll agree this is close to the "code this for me" territory, but I'll try to answer in a way that gets you on the right track, instead of just posting a working code snippet.
A simple way of doing this is just to use int()'s base argument, but I'm guessing that is disallowed.
You already have a way of testing the current bit in your question, namely checking whether n % 2 == 1. If this is the case, we need to add a power of two.
Then, we need some way of going to the next bit. In binary, we would use bit shifts, but sadly, we don't have those. a >> b is equivalent to a // (2**b) - can you write a decimal equivalent to that?
You also need to keep a counter of which power of two the current bit represents, a loop, and some way of detecting an end condition. Those are left as exercises to the reader.
I’d recommend reading the following articles on Wikipedia:
https://en.wikipedia.org/wiki/Radix
https://en.wikipedia.org/wiki/Binary_number
The first one gives you an idea how the numeral systems work in general and the second one explains and shows the formula to convert between binary and decimal systems.
Try to implement the solution after reading this. That’s what I did when I dealt with this problem. If that doesn’t help, let me know and I’ll post the code.
Hopefully, this code clarifies things a bit.
x = input("Enter binary number: ").strip()
decimal = 0
for i in range(len(x)):
decimal += int(x[i]) * 2**abs((i - (len(x) - 1)))
print(decimal)
This code takes in a binary number as a string, converts it to a decimal number and outputs it as an integer. The procedure is the following:
1st element of binary number * 2^(length of binary number - 1)
2nd element of binary number * 2^(length of binary number - 2)
and so on till we get to the last element and ...2^0
If we take number 10011, the conversion using this formula will look like this:
1*2^4 + 0*2^3 + 0*2^2 + 1*2^1 + 1*2^0, which equals to 19.
This code, however, assumes that the binary number is valid. Let me know if it helps.
Another implementation using while loop might look like this. Maybe it'll be easier to understand than the code with the for loop.
x = input("Enter binary number: ").strip()
decimal = 0
index = 0
exp = len(x) - 1
while index != len(x):
decimal += int(x[index]) * 2**exp
index += 1
exp -= 1
print(decimal)
In this one we start from the beginning of the number with the highest power, which is length of binary number minus one, we loop through the number, lowering the power and changing index.
Regarding checking if number is binary.
Try using helper function to determine if number is binary and then insert this function inside your main function. For example:
def is_binary(x):
""" Returns True if number x is binary and False otherwise.
input: x as a string
"""
for i in list(x):
if i not in ["1", "0"]:
return False
return True
def binary_decimal(x):
""" Converts binary to decimal.
input: binary number x as a string
output: decimal number as int
"""
if not is_binary(x):
return "Number is invalid"
decimal = 0
for i in range(len(x)):
decimal += int(x[i]) * 2**abs((i - (len(x) - 1)))
return decimal
The first function checks if number consists only of ones and zeros and the second function actually converts your number only if it's binary according to the first function.
You can also try using assert statement or try / except if you'd better raise an error if number is not binary instead of simply printing the message.
Of course, you can implement this solution without any functions.

How to read fixed point numbers in python

I would like to read an 8 bit number that comes in a 2's complement fix8_7 (8 bit number and the binary point is in the 7 bit). How can I do this in Python?
I am assuming that you have (starting from the left end) one sign bit, the assumed binary point, and then seven bits that represent a fractional value. If that's the case then you can just take the signed integer value of the fixed-point number and divide by 128. You'll need to do this division using floating-point values, of course, because the result will be less than 1.
The range of values that can be represented in this fixed-point format is -1.0 to +(127/128).
Assuming that your input is s = '1101001.1' (for example), you can use:
d = int(s[0:7],2)+int(s[8])/2.0
This will give an unsigned result of course. If you want to get a negative value for an input that starts with '1', then I guess that you can use d when s[0] == '0' and 64-d when s[0] == '1'.

Categories

Resources