I would like to create a function which gives the following things
32_bit_binary(-1) should be '11111111111111111111111111111111'
32_bit_binary(1) should be '00000000000000000000000000000001'
Now I gave the following code
def 32_bit_binary(num_bits):
return '{:032b}'.format(num_bits)
But when I gave this
print(32_bit_binary(-1))
it came -00000000000000000000000000000001
What is wrong with the code?
As #gspr said, formatting as base 2 doesn’t give you the actual representation. You can solve it by masking the negative integer, which has infinitely many leading 1s for the purposes of bitwise operations, down to 32 bits:
return f"{num_bits & 0xffff_ffff:032b}"
String formatting like {:032b} does not give you the actual representation of the number. It just writes the number in base-2. That's a purely mathematical operation. Implementation details like how the computer represents said number (like using binary, using 2's complement for negative numbers, etc.) are not in the scope of those string formatting operations.
A good way to get at the actual representations of values in Python is the struct module. For example, struct.pack("#i", -1) returns the bytestring b'\xff\xff\xff\xff'. Printing that bytestring in binary is left as an exercise to the reader.
PS: For numbers other than -1, you may be surprised by the output of struct.pack. The term you'll want to look up is endianness, and the # in my struct.pack formatting string.
Related
I have this example code:
test = 1011
test2 = int(test, 2)
print(test2)
which will throw an error saying
int() can't convert non-string with explicit base
The code works when i wrap test into str(), since the int-conversion needs a string as an input.
My question: Why is that so, and is there no easy way to convert on bases while accepting int? I find it rather counter-intuitive that an interger conversion method requires a string as an input.
Because applying it to integers makes no sense
In your example test is a number. It has no base. All numbers are like this: binary 0x1011, decimal 11 and hexadecimal 0x0B are the exact same number. The three ways of writing it are just different ways of writing down the same thing, just as using the Chinese character for 3, 三, would be. Internally, of course, in computers numbers represented in binary - e.g. 0b1111110011 - but can be displayed in any base you like. Bases are only relevant when converting a number to, or from, a string.
However, if you wanted to set test using a binary representation you could simply write:
test = 0b1011
This function only works on strings because the base is only relevant if you have a string representation of the number.
If you have an integer, there is no associated base, it's a number. And then, you can represent it as a string in base 2, 16 or 10 (or any other you want).
I am working on an encryption puzzle and am needing to take the exclusive or of two binary numbers (I'm using the operator package in Python). If I run operator.xor(1001111, 1100001) for instance I get the very weird output 2068086. Why doesn't it return 0101110 or at least 101110?
Because Python doesn't see that as binary numbers. Instead use:
operator.xor(0b1001111, 0b1100001)
The calculated answer is using the decimal values you provided, not their binary appearance. What you are really asking is...
1001111 ^ 1100001
When you mean is 79 ^ 97. Instead try using the binary literals as so...
0b1001111 ^ 0b1100001
See How do you express binary literals in Python? for more information.
Because 1001111 and 1100001 are not binary numbers. 1001111 is One million, one thousand, one hundred and eleven, while 1100001 is One million, one hundred thousands and one. Python doesn't recognize these as binary numbers. Binary numbers have to be prefixed with 0b to be recognized as binary numbers in Python/Python 3. So the correct way is this:
operator.xor(0b1001111, 0b1100001)
But hey! We get 46 as output. We should fix that. Thankfully, there IS a built-in in Python/Python 3. It's the function bin(n). That function prints a number a binary, prefixed with 0b. So our final code would be:
bin(operator.xor(0b1001111, 0b1100001))
If we want to hide the 0b (mostly in cases where that number is printed to the screen), we should use [2:] like this:
bin(operator.xor(0b1001111, 0b1100001))[2:]
A shorter way (warning looks like a tutorial for something you *should* already know)
Well, operator.xor() is too big for an operator :)
If that is the case (99.9%), instead you should use a^b. I think you already know this but why to import a whole module just for the xor operator? If you like to type the word xor instead, import the operator module like this: from operator import a, b.... Then use like this: bin(xor(a,b)). I hope you already know that stuff but I want to make sure you enjoy coding even more :)
I am trying to create a binary number that contains a fraction. Something like this:
0b110.101
However, this gives a syntax error.
0b110
works fine though. How do you create a binary number that is not an integer?
How do you create a binary number that is not an integer?
Binary is a text representation of a number. String are used to store text, so one would use something like the following:
"110.101"
But I think you misstated your question. You don't want the binary representation of a number, you want the number itself. 110.1012 represents the number six and five eight. There are infinite ways to create create that number, including the following:
6 + 5/8
6.625
That said, I suspect you'd prefer to see the binary representation of the number in the source. Unfortunately, Python does not have decimal binary number literals. You could use
0b110101 / (1>>3)
bin_to_num("110.101")
Writing bin_to_num is left as an exercise to the reader.
You use the Binary fractions package.
This let's you convert binary-fraction strings into numbers and vice-versa
Example:
>>> from binary_fractions import Binary
>>> str(Binary(6.625))
'0b110.101'
>>> float(Binary("0b110.101"))
6.625
It has many more helper functions to manipulate binary strings such as: shift, add, fill, to_exponential, invert...
PS: Shameless plug, I'm the author of this package.
I am depending on some code that uses the Decimal class because it needs precision to a certain number of decimal places. Some of the functions allow inputs to be floats because of the way that it interfaces with other parts of the codebase. To convert them to decimal objects, it uses things like
mydec = decimal.Decimal(str(x))
where x is the float taken as input. My question is, does anyone know what the standard is for the 'str' method as applied to floats?
For example, take the number 2.1234512. It is stored internally as 2.12345119999999999 because of how floats are represented.
>>> x = 2.12345119999999999
>>> x
2.1234511999999999
>>> str(x)
'2.1234512'
Ok, str(x) in this case is doing something like '%.6f' % x. This is a problem with the way my code converts to decimals. Take the following:
>>> d = decimal.Decimal('2.12345119999999999')
>>> ds = decimal.Decimal(str(2.12345119999999999))
>>> d - ds
Decimal('-1E-17')
So if I have the float, 2.12345119999999999, and I want to pass it to Decimal, converting it to a string using str() gets me the wrong answer. I need to know what are the rules for str(x) that determine what the formatting will be, because I need to determine whether this code needs to be re-written to avoid this error (note that it might be OK, because, for example, the code might round to the 10th decimal place once we have a decimal object)
There must be some set of rules in python's docs that hopefully someone here can point me to. Thanks!
In the Python source, look in "Include/floatobject.h". The precision for the string conversion is set a few lines from the top after an comment with some explanation of the choice:
/* The str() precision PyFloat_STR_PRECISION is chosen so that in most cases,
the rounding noise created by various operations is suppressed, while
giving plenty of precision for practical use. */
#define PyFloat_STR_PRECISION 12
You have the option of rebuilding, if you need something different. Any changes will change formatting of floats and complex numbers. See ./Objects/complexobject.c and ./Objects/floatobject.c. Also, you can compare the difference between how repr and str convert doubles in these two files.
There's a couple of issues worth discussing here, but the summary is: you cannot extract information that is not stored on your system already.
If you've taken a decimal number and stored it as a floating point, you'll have lost information, since most decimal (base 10) numbers with a finite number of digits cannot be stored using a finite number of digits in base 2 (binary).
As was mentioned, str(a_float) will really call a_float.__str__(). As the documentation states, the purpose of that method is to
return a string containing a nicely printable representation of an object
There's no particular definition for the float case. My opinion is that, for your purposes, you should consider __str__'s behavior to be undefined, since there's no official documentation on it - the current implementation can change anytime.
If you don't have the original strings, there's no way to extract the missing digits of the decimal representation from the float objects. All you can do is round predictably, using string formatting (which you mention):
Decimal( "{0:.5f}".format(a_float) )
You can also remove 0s on the right with resulting_string.rstrip("0").
Again, this method does not recover the information that has been lost.
I am trying to write a method in Python 3.2 that encrypts a phrase and then decrypts it. The problem is that the numbers are so big that when Python does math with them it immediately converts it into scientific notation. Since my code requires all the numbers to function scientific notation, this is not useful.
What I have is:
coded = ((eval(input(':'))+1213633288469888484)/2)+1042
Basically, I just get a number from the user and do some math to it.
I have tried format() and a couple other things but I can't get them to work.
EDIT: I use only even integers.
In python3, '/' does real division (e.g. floating point). To get integer division, you need to use //. In other words 100/2 yields 50.0 (float) whereas 100//2 yields 50 (integer)
Your code probably needs to be changed as:
coded = ((eval(input(':'))+1213633288469888484)//2)+1042
As a cautionary tale however, you may want to consider using int instead of eval:
coded = ((int(input(':'))+1213633288469888484)//2)+1042
If you know that the floating point value is really an integer, or you don't care about dropping the fractional part, you can just convert it to an int before you print it.
>>> print 1.2e16
1.2e+16
>>> print int(1.2e16)
12000000000000000