mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-11-23 21:11:08 +00:00
Added binary shifts and twos complement functions to bit manipulation (#4068)
* Added binary shifts and twos complement functions to bit manipulation package * Fixed problem representing 0 wrong * More testing * Fixed problems * Fixed formatting * More format fixes * Format fixes * Fixed docstrings and added url * Minor change to url
This commit is contained in:
parent
61f3119467
commit
02d9bc66c1
111
bit_manipulation/binary_shifts.py
Normal file
111
bit_manipulation/binary_shifts.py
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
# Information on binary shifts:
|
||||||
|
# https://docs.python.org/3/library/stdtypes.html#bitwise-operations-on-integer-types
|
||||||
|
# https://www.interviewcake.com/concept/java/bit-shift
|
||||||
|
|
||||||
|
|
||||||
|
def logical_left_shift(number: int, shift_amount: int) -> str:
|
||||||
|
"""
|
||||||
|
Take in 2 positive integers.
|
||||||
|
'number' is the integer to be logically left shifted 'shift_amount' times.
|
||||||
|
i.e. (number << shift_amount)
|
||||||
|
Return the shifted binary representation.
|
||||||
|
|
||||||
|
>>> logical_left_shift(0, 1)
|
||||||
|
'0b00'
|
||||||
|
>>> logical_left_shift(1, 1)
|
||||||
|
'0b10'
|
||||||
|
>>> logical_left_shift(1, 5)
|
||||||
|
'0b100000'
|
||||||
|
>>> logical_left_shift(17, 2)
|
||||||
|
'0b1000100'
|
||||||
|
>>> logical_left_shift(1983, 4)
|
||||||
|
'0b111101111110000'
|
||||||
|
>>> logical_left_shift(1, -1)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: both inputs must be positive integers
|
||||||
|
"""
|
||||||
|
if number < 0 or shift_amount < 0:
|
||||||
|
raise ValueError("both inputs must be positive integers")
|
||||||
|
|
||||||
|
binary_number = str(bin(number))
|
||||||
|
binary_number += "0" * shift_amount
|
||||||
|
return binary_number
|
||||||
|
|
||||||
|
|
||||||
|
def logical_right_shift(number: int, shift_amount: int) -> str:
|
||||||
|
"""
|
||||||
|
Take in positive 2 integers.
|
||||||
|
'number' is the integer to be logically right shifted 'shift_amount' times.
|
||||||
|
i.e. (number >>> shift_amount)
|
||||||
|
Return the shifted binary representation.
|
||||||
|
|
||||||
|
>>> logical_right_shift(0, 1)
|
||||||
|
'0b0'
|
||||||
|
>>> logical_right_shift(1, 1)
|
||||||
|
'0b0'
|
||||||
|
>>> logical_right_shift(1, 5)
|
||||||
|
'0b0'
|
||||||
|
>>> logical_right_shift(17, 2)
|
||||||
|
'0b100'
|
||||||
|
>>> logical_right_shift(1983, 4)
|
||||||
|
'0b1111011'
|
||||||
|
>>> logical_right_shift(1, -1)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: both inputs must be positive integers
|
||||||
|
"""
|
||||||
|
if number < 0 or shift_amount < 0:
|
||||||
|
raise ValueError("both inputs must be positive integers")
|
||||||
|
|
||||||
|
binary_number = str(bin(number))[2:]
|
||||||
|
if shift_amount >= len(binary_number):
|
||||||
|
return "0b0"
|
||||||
|
shifted_binary_number = binary_number[: len(binary_number) - shift_amount]
|
||||||
|
return "0b" + shifted_binary_number
|
||||||
|
|
||||||
|
|
||||||
|
def arithmetic_right_shift(number: int, shift_amount: int) -> str:
|
||||||
|
"""
|
||||||
|
Take in 2 integers.
|
||||||
|
'number' is the integer to be arithmetically right shifted 'shift_amount' times.
|
||||||
|
i.e. (number >> shift_amount)
|
||||||
|
Return the shifted binary representation.
|
||||||
|
|
||||||
|
>>> arithmetic_right_shift(0, 1)
|
||||||
|
'0b00'
|
||||||
|
>>> arithmetic_right_shift(1, 1)
|
||||||
|
'0b00'
|
||||||
|
>>> arithmetic_right_shift(-1, 1)
|
||||||
|
'0b11'
|
||||||
|
>>> arithmetic_right_shift(17, 2)
|
||||||
|
'0b000100'
|
||||||
|
>>> arithmetic_right_shift(-17, 2)
|
||||||
|
'0b111011'
|
||||||
|
>>> arithmetic_right_shift(-1983, 4)
|
||||||
|
'0b111110000100'
|
||||||
|
"""
|
||||||
|
if number >= 0: # Get binary representation of positive number
|
||||||
|
binary_number = "0" + str(bin(number)).strip("-")[2:]
|
||||||
|
else: # Get binary (2's complement) representation of negative number
|
||||||
|
binary_number_length = len(bin(number)[3:]) # Find 2's complement of number
|
||||||
|
binary_number = bin(abs(number) - (1 << binary_number_length))[3:]
|
||||||
|
binary_number = (
|
||||||
|
("1" + "0" * (binary_number_length - len(binary_number)) + binary_number)
|
||||||
|
if number < 0
|
||||||
|
else "0"
|
||||||
|
)
|
||||||
|
|
||||||
|
if shift_amount >= len(binary_number):
|
||||||
|
return "0b" + binary_number[0] * len(binary_number)
|
||||||
|
return (
|
||||||
|
"0b"
|
||||||
|
+ binary_number[0] * shift_amount
|
||||||
|
+ binary_number[: len(binary_number) - shift_amount]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod()
|
43
bit_manipulation/binary_twos_complement.py
Normal file
43
bit_manipulation/binary_twos_complement.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
# Information on 2's complement: https://en.wikipedia.org/wiki/Two%27s_complement
|
||||||
|
|
||||||
|
|
||||||
|
def twos_complement(number: int) -> str:
|
||||||
|
"""
|
||||||
|
Take in a negative integer 'number'.
|
||||||
|
Return the two's complement representation of 'number'.
|
||||||
|
|
||||||
|
>>> twos_complement(0)
|
||||||
|
'0b0'
|
||||||
|
>>> twos_complement(-1)
|
||||||
|
'0b11'
|
||||||
|
>>> twos_complement(-5)
|
||||||
|
'0b1011'
|
||||||
|
>>> twos_complement(-17)
|
||||||
|
'0b101111'
|
||||||
|
>>> twos_complement(-207)
|
||||||
|
'0b100110001'
|
||||||
|
>>> twos_complement(1)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: input must be a negative integer
|
||||||
|
"""
|
||||||
|
if number > 0:
|
||||||
|
raise ValueError("input must be a negative integer")
|
||||||
|
binary_number_length = len(bin(number)[3:])
|
||||||
|
twos_complement_number = bin(abs(number) - (1 << binary_number_length))[3:]
|
||||||
|
twos_complement_number = (
|
||||||
|
(
|
||||||
|
"1"
|
||||||
|
+ "0" * (binary_number_length - len(twos_complement_number))
|
||||||
|
+ twos_complement_number
|
||||||
|
)
|
||||||
|
if number < 0
|
||||||
|
else "0"
|
||||||
|
)
|
||||||
|
return "0b" + twos_complement_number
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod()
|
Loading…
Reference in New Issue
Block a user