~ operator binary complement

All ESP8266 boards running MicroPython.
Official boards are the Adafruit Huzzah and Feather boards.
Target audience: MicroPython users with an ESP8266 board.
cyberlab
Posts: 56
Joined: Sat Apr 21, 2018 5:02 am

~ operator binary complement

Post by cyberlab » Sat Apr 21, 2018 5:09 am

it seems that the operator ~ is not implemented in micropython, what is the best way to complement a byte? thanks in advance.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: ~ operator binary complement

Post by pythoncoder » Sun Apr 22, 2018 9:18 am

It is implemented:

Code: Select all

>>> a = b'\x01'
>>> ~a[0]
-2
>>> 
The 1's complement of 1 is 11111110 which, viewed as a signed number in 2's complement notation, is -2.
Peter Hinch
Index to my micropython libraries.

cyberlab
Posts: 56
Joined: Sat Apr 21, 2018 5:02 am

Re: ~ operator binary complement

Post by cyberlab » Thu Apr 26, 2018 3:24 am

hello thank you for answering pythoncoder, I am learning to program in micropython with a nodemcu module, well the question is that in my application I need to read a binary file one byte at a time complement it and send it to a machinein parallel fashion, is already working but the complementation I do it by harware with a integrated circuit 74ls240 because I do not know how to do it by software.

with open("Design.DST", "rb") as f: # open design file in binary.
f.seek(511) # point to start of design data.
byte = f.read(1) # buffer one byte only.
while byte != b"": # read until end of design
if D_set.value()== False: #Request data from machine.
byte = f.read(1) # read design file byte by byte.
i2c.writeto(0x20,byte) # write to output port.


this is part of the code what I need to complement is the variable byte in such a way that if its value is 63 when complementing it it is equal to 9C.
deal with byte = ~ (f.read (1))
or using another variable inv = ~byte
or inv = ~byte[0]


hahaha I think I made the harder and this look so simple I can't do it.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: ~ operator binary complement

Post by dhylands » Thu Apr 26, 2018 6:32 am

f.read(1) returns a bytes object with zero or one elements.

So ~(f.read(1)) is invalid. ~f.read(1)[0] would be valid in the case that f.read(1) returns 1 byte, but wouldn't be valid if f.read(1) returns zero bytes.

So storing the data into a variable and checking the variable length for > 0 is the best way to do it.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: ~ operator binary complement

Post by pythoncoder » Thu Apr 26, 2018 7:06 am

There is another issue here. Bitwise operations in Python have a subtlety based on the fact that Python supports arithmetic with arbitrary precision. So if you ones-complement a value you get a negative result

Code: Select all

>>> print(hex(~0x63))
-0x64
>>> 
The value -0x64 is surprising until you consider what numbers look like in arbitrary precision arithmetic. 0x63 notionally has an infinite number of leading 0's, so its one's complement has an infinite number of leading 1's. The only sensible way to represent this is as a negative number. This can confuse those of us with a background in hardware or languages with fixed size integers.

To constrain things to 8 bits you can use the exclusive or operator ^ with an 8 bit operand:

Code: Select all

>>> hex(0x63^0xff)
'0x9c'
>>> hex(0x9c^0xff)
'0x63'
>>> 
Or use the ~ operator and constrain to 8 bits with a logical and:

Code: Select all

>>> print(hex(~0x63 & 0xff))
0x9c
>>> 
Peter Hinch
Index to my micropython libraries.

cyberlab
Posts: 56
Joined: Sat Apr 21, 2018 5:02 am

Re: ~ operator binary complement

Post by cyberlab » Fri Apr 27, 2018 4:13 am

hello, thanks again for your time answering, dhylans deal with byte = ~ f.read (1) [0] but TypeError: object with buffer protocol required. and pythoncoder deal with byte = f.read (1) ^ 0xff as well bitwise = byte ^ 0xff but TypeError: unsupported types for __xor__: 'bytes', 'int' and with bitwise = hex (byte ^ 0xff) SyntaxError: invalid syntax for integer with base 10
Sorry but remember that I am new and I try to learn, thanks again for your time.

OutoftheBOTS_
Posts: 847
Joined: Mon Nov 20, 2017 10:18 am

Re: ~ operator binary complement

Post by OutoftheBOTS_ » Fri Apr 27, 2018 6:39 am

Hopefully I can help some.

~ is definitely implemented and as far as I can tell it works the same way as CPython.

I think that you don't understand how python stores data in its memory. So signed integers are stored in 4 bytes of memory with a method know as two's complement see https://en.wikipedia.org/wiki/Two%27s_complement.

See this 1 byte version.
8 bit.JPG
8 bit.JPG (72.59 KiB) Viewed 8699 times
You can see storing the number 1 in a 1 byte of memory and flip all the bits then you will get how -2 is stored.

Now looking at it as a human this looks a super strange way to store number but then if you start to do math addition the way a computer then it will make sense. Get the way -2 is stored then add add the way 1 is stored to it and see whast the result is then add 1 again and you can see this makes it easy to add negitive and positive numbers.

Looking at the table fo numbers you can also see why ~a = -a-1

cyberlab
Posts: 56
Joined: Sat Apr 21, 2018 5:02 am

Re: ~ operator binary complement

Post by cyberlab » Fri Apr 27, 2018 3:44 pm

good day OutoftheBOTS_ thanks for answering, then according to the information I need the complement of an unsigned byte as well as the zero number ie 00000000 = 11111111 then it would be the option byte ^ 0xff, but I do not know how to implement it so that I do not get errors before mentioned.

OutoftheBOTS_
Posts: 847
Joined: Mon Nov 20, 2017 10:18 am

Re: ~ operator binary complement

Post by OutoftheBOTS_ » Fri Apr 27, 2018 8:04 pm

First of all can you please post your code in code tags so that it is readable for us with correct spacing. To get code tags just press the icon that looks like </> and paste your code between the 2 code tags. Please use # and commit out what you want us to know and where your problem is.

Also I have loticed from your code is that you read 1 byte at a time into a byte array of size 1.

byte = f.read(1)

Will result in byte[0] = to the read byte

you can just use this byte = f.read(1)[0] then byte won't be an array.

Also do beware that although your calling it a byte it is in fact a signed integer of size 4 bytes because is how python stores data in memory. Python will read 1 byte from the file then store it into 4 bytes in memory and treat it as a signed int.

So if you want to do biniary operations on it as a unsigned byte then you need to cut off the excess 3 bytes.

Code: Select all

byte = f.read(1)[0]
#find the inverse of just the first byte by using &0xff to cut off everything outside first byte
byte_inverse = ~byte & 0xff

cyberlab
Posts: 56
Joined: Sat Apr 21, 2018 5:02 am

Re: ~ operator binary complement

Post by cyberlab » Fri Apr 27, 2018 9:10 pm

hello again and thanks for your interest, my project consists of 2 applications one is installed on a pc and consists of sending a binary file to an esp8266 module via wifi and the second is the one I install in that module which consists of reading the binary file of one byte at a time complement the bits and send it in parallel to a machine through a serial to parallel i2c ic.
up to now it works but the complement of the bits is done by hardware with a 74ls240 ic.
my intention is to perfect it so that the complement of the bits is in software and thus save an ic.
in such a way when byte = 00000000 after inverting it is byte = 11111111 and so with all 255 different one-byte values, but I could not do it, thank you very much for your help.

this is part of code of interest:

Code: Select all

with open("Design.DST", "rb") as f: # open design file in binary.
            f.seek(511) # point to start of design data. 
            byte = f.read(1) # buffer one byte only.
            lcd.move_to(0,1)
            lcd.putstr("Sending >")
            while byte != b"": # read until end of design file.
                if D_set.value()== False: #Request data from machine.
                    time_out=0
                    byte = f.read(1) # the value of byte i need the complement ej: byte = 0x00 after complement byte = 0xff
                    i2c.writeto(0x20,byte) # write to output port.
                    time.sleep_us(1)# delay for stable data on output port
                    Strobe.value(1) # strobe pulse for machine.
                    time.sleep_us(10) # width of strobe pulse.
                    Strobe.value(0) 

Post Reply