From 19c0aee031c5fe6c9f1cab0f0e9bbfee31739916 Mon Sep 17 00:00:00 2001 From: Leyza Date: Sat, 26 Dec 2020 22:45:01 -0500 Subject: [PATCH 1/9] Added binary shifts and twos complement functions to bit manipulation package --- bit_manipulation/binary_shifts.py | 94 ++++++++++++++++++++++ bit_manipulation/binary_twos_complement.py | 30 +++++++ 2 files changed, 124 insertions(+) create mode 100644 bit_manipulation/binary_shifts.py create mode 100644 bit_manipulation/binary_twos_complement.py diff --git a/bit_manipulation/binary_shifts.py b/bit_manipulation/binary_shifts.py new file mode 100644 index 000000000000..944af2080f20 --- /dev/null +++ b/bit_manipulation/binary_shifts.py @@ -0,0 +1,94 @@ +from binary_twos_complement import twos_complement + + +def logical_left_shift(a: int, b: int) -> str: + """ + Take in 2 positive integers. + 'a' is the integer to be logically left shifted 'b' times. + i.e. (a << b) + Return the shifted binary representation. + + >>> 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 a < 0 or b < 0: + raise ValueError("both inputs must be positive integers") + + binary_a = str(bin(a)) + binary_a += '0' * b + return binary_a + + +def logical_right_shift(a: int, b: int) -> str: + """ + Take in positive 2 integers. + 'a' is the integer to be logically right shifted 'b' times. + i.e. (a >> b) + Return the shifted binary representation. + + >>> 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 a < 0 or b < 0: + raise ValueError("both inputs must be positive integers") + + binary_a = str(bin(a))[2:] + if b >= len(binary_a): + return '0b0' + shifted_binary_a = binary_a[:len(binary_a) - b] + return '0b' + shifted_binary_a + + +def arithmetic_right_shift(a: int, b: int) -> str: + """ + Take in 2 integers. + 'a' is the integer to be arithmetically right shifted 'b' times. + 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 a >= 0: + binary_a = '0' + str(bin(a)).strip('-')[2:] + else: + binary_a = twos_complement(a)[2:] + + if b >= len(binary_a): + return '0b' + binary_a[0] * len(binary_a) + return '0b' + binary_a[0] * b + binary_a[:len(binary_a) - b] + + +if __name__ == "__main__": + import doctest + + doctest.testmod() diff --git a/bit_manipulation/binary_twos_complement.py b/bit_manipulation/binary_twos_complement.py new file mode 100644 index 000000000000..892c58c8a8fc --- /dev/null +++ b/bit_manipulation/binary_twos_complement.py @@ -0,0 +1,30 @@ +def twos_complement(a: int) -> str: + """ + Take in a negative integer 'a'. + Return the two's complement representation of 'a'. + + >>> 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 a > 0: + raise ValueError("input must be a negative integer") + bit_a_length = len(bin(a)[3:]) + twos_complement_a = bin(abs(a) - (1 << bit_a_length))[3:] + twos_complement_a = '1' + '0' * (bit_a_length - len(twos_complement_a)) + twos_complement_a + return '0b' + twos_complement_a + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From ec0fe34ffcb014949ba707293423e6eb032db74f Mon Sep 17 00:00:00 2001 From: Leyza Date: Sat, 26 Dec 2020 23:13:00 -0500 Subject: [PATCH 2/9] Fixed problem representing 0 wrong --- bit_manipulation/binary_twos_complement.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/bit_manipulation/binary_twos_complement.py b/bit_manipulation/binary_twos_complement.py index 892c58c8a8fc..114062d6f0dd 100644 --- a/bit_manipulation/binary_twos_complement.py +++ b/bit_manipulation/binary_twos_complement.py @@ -3,6 +3,8 @@ def twos_complement(a: int) -> str: Take in a negative integer 'a'. Return the two's complement representation of 'a'. + >>> twos_complement(0) + '0b0' >>> twos_complement(-1) '0b11' >>> twos_complement(-5) @@ -18,9 +20,10 @@ def twos_complement(a: int) -> str: """ if a > 0: raise ValueError("input must be a negative integer") - bit_a_length = len(bin(a)[3:]) - twos_complement_a = bin(abs(a) - (1 << bit_a_length))[3:] - twos_complement_a = '1' + '0' * (bit_a_length - len(twos_complement_a)) + twos_complement_a + binary_a_length = len(bin(a)[3:]) + twos_complement_a = bin(abs(a) - (1 << binary_a_length))[3:] + twos_complement_a = ('1' + '0' * (binary_a_length - len(twos_complement_a)) + + twos_complement_a) if a < 0 else '0' return '0b' + twos_complement_a From 6911d3bcfa722e1650bff62d5c44c1e379ad92cd Mon Sep 17 00:00:00 2001 From: Leyza Date: Sat, 26 Dec 2020 23:23:46 -0500 Subject: [PATCH 3/9] More testing --- bit_manipulation/binary_shifts.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bit_manipulation/binary_shifts.py b/bit_manipulation/binary_shifts.py index 944af2080f20..f7980163c431 100644 --- a/bit_manipulation/binary_shifts.py +++ b/bit_manipulation/binary_shifts.py @@ -8,6 +8,8 @@ def logical_left_shift(a: int, b: int) -> str: i.e. (a << b) Return the shifted binary representation. + >>> logical_left_shift(0, 1) + '0b00' >>> logical_left_shift(1, 1) '0b10' >>> logical_left_shift(1, 5) @@ -36,6 +38,8 @@ def logical_right_shift(a: int, b: int) -> str: i.e. (a >> b) Return the shifted binary representation. + >>> logical_right_shift(0, 1) + '0b0' >>> logical_right_shift(1, 1) '0b0' >>> logical_right_shift(1, 5) From 73dbc933ff281c479abf1a3fcb62e8b5ff7a7f1b Mon Sep 17 00:00:00 2001 From: Leyza Date: Sun, 27 Dec 2020 00:06:02 -0500 Subject: [PATCH 4/9] Fixed problems --- bit_manipulation/binary_shifts.py | 47 +++++++++++----------- bit_manipulation/binary_twos_complement.py | 15 +++---- 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/bit_manipulation/binary_shifts.py b/bit_manipulation/binary_shifts.py index f7980163c431..84add147c5ed 100644 --- a/bit_manipulation/binary_shifts.py +++ b/bit_manipulation/binary_shifts.py @@ -1,7 +1,4 @@ -from binary_twos_complement import twos_complement - - -def logical_left_shift(a: int, b: int) -> str: +def logical_left_shift(number: int, shift_amount: int) -> str: """ Take in 2 positive integers. 'a' is the integer to be logically left shifted 'b' times. @@ -23,15 +20,15 @@ def logical_left_shift(a: int, b: int) -> str: ... ValueError: both inputs must be positive integers """ - if a < 0 or b < 0: + if number < 0 or shift_amount < 0: raise ValueError("both inputs must be positive integers") - binary_a = str(bin(a)) - binary_a += '0' * b - return binary_a + binary_number = str(bin(number)) + binary_number += "0" * shift_amount + return binary_number -def logical_right_shift(a: int, b: int) -> str: +def logical_right_shift(number: int, shift_amount: int) -> str: """ Take in positive 2 integers. 'a' is the integer to be logically right shifted 'b' times. @@ -53,17 +50,17 @@ def logical_right_shift(a: int, b: int) -> str: ... ValueError: both inputs must be positive integers """ - if a < 0 or b < 0: + if number < 0 or shift_amount < 0: raise ValueError("both inputs must be positive integers") - binary_a = str(bin(a))[2:] - if b >= len(binary_a): - return '0b0' - shifted_binary_a = binary_a[:len(binary_a) - b] - return '0b' + shifted_binary_a + 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(a: int, b: int) -> str: +def arithmetic_right_shift(number: int, shift_amount: int) -> str: """ Take in 2 integers. 'a' is the integer to be arithmetically right shifted 'b' times. @@ -82,14 +79,18 @@ def arithmetic_right_shift(a: int, b: int) -> str: >>> arithmetic_right_shift(-1983, 4) '0b111110000100' """ - if a >= 0: - binary_a = '0' + str(bin(a)).strip('-')[2:] - else: - binary_a = twos_complement(a)[2:] + 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 b >= len(binary_a): - return '0b' + binary_a[0] * len(binary_a) - return '0b' + binary_a[0] * b + binary_a[:len(binary_a) - b] + 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__": diff --git a/bit_manipulation/binary_twos_complement.py b/bit_manipulation/binary_twos_complement.py index 114062d6f0dd..9923527c7f6e 100644 --- a/bit_manipulation/binary_twos_complement.py +++ b/bit_manipulation/binary_twos_complement.py @@ -1,4 +1,4 @@ -def twos_complement(a: int) -> str: +def twos_complement(number: int) -> str: """ Take in a negative integer 'a'. Return the two's complement representation of 'a'. @@ -18,13 +18,14 @@ def twos_complement(a: int) -> str: ... ValueError: input must be a negative integer """ - if a > 0: + if number > 0: raise ValueError("input must be a negative integer") - binary_a_length = len(bin(a)[3:]) - twos_complement_a = bin(abs(a) - (1 << binary_a_length))[3:] - twos_complement_a = ('1' + '0' * (binary_a_length - len(twos_complement_a)) + - twos_complement_a) if a < 0 else '0' - return '0b' + twos_complement_a + 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__": From 919af320fdaf3ef67873697d3ccd883383a3ca9f Mon Sep 17 00:00:00 2001 From: Leyza Date: Sun, 27 Dec 2020 00:13:05 -0500 Subject: [PATCH 5/9] Fixed formatting --- bit_manipulation/binary_shifts.py | 16 +++++++++++----- bit_manipulation/binary_twos_complement.py | 12 +++++++++--- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/bit_manipulation/binary_shifts.py b/bit_manipulation/binary_shifts.py index 84add147c5ed..579a89f1c0b2 100644 --- a/bit_manipulation/binary_shifts.py +++ b/bit_manipulation/binary_shifts.py @@ -56,7 +56,7 @@ def logical_right_shift(number: int, shift_amount: int) -> str: binary_number = str(bin(number))[2:] if shift_amount >= len(binary_number): return "0b0" - shifted_binary_number = binary_number[:len(binary_number) - shift_amount] + shifted_binary_number = binary_number[: len(binary_number) - shift_amount] return "0b" + shifted_binary_number @@ -84,13 +84,19 @@ def arithmetic_right_shift(number: int, shift_amount: int) -> str: 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" + 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] + return ( + "0b" + + binary_number[0] * shift_amount + + binary_number[:len(binary_number) - shift_amount] + ) if __name__ == "__main__": diff --git a/bit_manipulation/binary_twos_complement.py b/bit_manipulation/binary_twos_complement.py index 9923527c7f6e..7ff4a97544a6 100644 --- a/bit_manipulation/binary_twos_complement.py +++ b/bit_manipulation/binary_twos_complement.py @@ -22,9 +22,15 @@ def twos_complement(number: int) -> str: 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" + 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 From b7658fbde0139ffac934d6f4814bcd27cd8632dc Mon Sep 17 00:00:00 2001 From: Leyza Date: Sun, 27 Dec 2020 00:19:59 -0500 Subject: [PATCH 6/9] More format fixes --- bit_manipulation/binary_shifts.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bit_manipulation/binary_shifts.py b/bit_manipulation/binary_shifts.py index 579a89f1c0b2..e920e09ebb00 100644 --- a/bit_manipulation/binary_shifts.py +++ b/bit_manipulation/binary_shifts.py @@ -93,9 +93,9 @@ def arithmetic_right_shift(number: int, shift_amount: int) -> str: 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] + "0b" + + binary_number[0] * shift_amount + + binary_number[:len(binary_number) - shift_amount] ) From cbc0a396cabb985ef1c3c8ac67f1ff13ae83f3c3 Mon Sep 17 00:00:00 2001 From: Leyza Date: Sun, 27 Dec 2020 00:43:16 -0500 Subject: [PATCH 7/9] Format fixes --- bit_manipulation/binary_shifts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bit_manipulation/binary_shifts.py b/bit_manipulation/binary_shifts.py index e920e09ebb00..e8d45fb255ea 100644 --- a/bit_manipulation/binary_shifts.py +++ b/bit_manipulation/binary_shifts.py @@ -95,7 +95,7 @@ def arithmetic_right_shift(number: int, shift_amount: int) -> str: return ( "0b" + binary_number[0] * shift_amount - + binary_number[:len(binary_number) - shift_amount] + + binary_number[: len(binary_number) - shift_amount] ) From b7750e17345311701d8a50b047a9a6960ad0a103 Mon Sep 17 00:00:00 2001 From: Leyza Date: Sun, 31 Jan 2021 17:10:44 -0500 Subject: [PATCH 8/9] Fixed docstrings and added url --- bit_manipulation/binary_shifts.py | 15 ++++++++++----- bit_manipulation/binary_twos_complement.py | 7 +++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/bit_manipulation/binary_shifts.py b/bit_manipulation/binary_shifts.py index e8d45fb255ea..d09ce630bfe0 100644 --- a/bit_manipulation/binary_shifts.py +++ b/bit_manipulation/binary_shifts.py @@ -1,8 +1,12 @@ +# 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. - 'a' is the integer to be logically left shifted 'b' times. - i.e. (a << b) + '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) @@ -31,8 +35,8 @@ def logical_left_shift(number: int, shift_amount: int) -> str: def logical_right_shift(number: int, shift_amount: int) -> str: """ Take in positive 2 integers. - 'a' is the integer to be logically right shifted 'b' times. - i.e. (a >> b) + '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) @@ -63,7 +67,8 @@ def logical_right_shift(number: int, shift_amount: int) -> str: def arithmetic_right_shift(number: int, shift_amount: int) -> str: """ Take in 2 integers. - 'a' is the integer to be arithmetically right shifted 'b' times. + '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) diff --git a/bit_manipulation/binary_twos_complement.py b/bit_manipulation/binary_twos_complement.py index 7ff4a97544a6..2c064ec142d7 100644 --- a/bit_manipulation/binary_twos_complement.py +++ b/bit_manipulation/binary_twos_complement.py @@ -1,7 +1,10 @@ +# Information on 2's complement: https://en.wikipedia.org/wiki/Two%27s_complement + + def twos_complement(number: int) -> str: """ - Take in a negative integer 'a'. - Return the two's complement representation of 'a'. + Take in a negative integer 'number'. + Return the two's complement representation of 'number'. >>> twos_complement(0) '0b0' From b7ebf35840d0cb7475016a23634da6d75da92072 Mon Sep 17 00:00:00 2001 From: Leyza Date: Sun, 31 Jan 2021 17:20:32 -0500 Subject: [PATCH 9/9] Minor change to url --- bit_manipulation/binary_shifts.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bit_manipulation/binary_shifts.py b/bit_manipulation/binary_shifts.py index d09ce630bfe0..fe62880f941c 100644 --- a/bit_manipulation/binary_shifts.py +++ b/bit_manipulation/binary_shifts.py @@ -1,4 +1,5 @@ -# Information on binary shifts: https://docs.python.org/3/library/stdtypes.html#bitwise-operations-on-integer-types +# 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