diff options
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/numeric.py | 90 | ||||
-rw-r--r-- | numpy/core/tests/test_deprecations.py | 34 | ||||
-rw-r--r-- | numpy/core/tests/test_numeric.py | 19 |
3 files changed, 92 insertions, 51 deletions
diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py index 9ddc3c546..551d63a01 100644 --- a/numpy/core/numeric.py +++ b/numpy/core/numeric.py @@ -2090,31 +2090,6 @@ def isscalar(num): else: return type(num) in ScalarType -_lkup = { - '0':'0000', - '1':'0001', - '2':'0010', - '3':'0011', - '4':'0100', - '5':'0101', - '6':'0110', - '7':'0111', - '8':'1000', - '9':'1001', - 'a':'1010', - 'b':'1011', - 'c':'1100', - 'd':'1101', - 'e':'1110', - 'f':'1111', - 'A':'1010', - 'B':'1011', - 'C':'1100', - 'D':'1101', - 'E':'1110', - 'F':'1111', - 'L':''} - def binary_repr(num, width=None): """ Return the binary representation of the input number as a string. @@ -2134,8 +2109,18 @@ def binary_repr(num, width=None): num : int Only an integer decimal number can be used. width : int, optional - The length of the returned string if `num` is positive, the length of - the two's complement if `num` is negative. + The length of the returned string if `num` is positive, or the length + of the two's complement if `num` is negative, provided that `width` is + at least a sufficient number of bits for `num` to be represented in the + designated form. + + If the `width` value is insufficient, it will be ignored, and `num` will + be returned in binary(`num` > 0) or two's complement (`num` < 0) form + with its width equal to the minimum number of bits needed to represent + the number in the designated form. This behavior is deprecated and will + later raise an error. + + .. deprecated:: 1.12.0 Returns ------- @@ -2146,6 +2131,7 @@ def binary_repr(num, width=None): -------- base_repr: Return a string representation of a number in the given base system. + bin: Python's built-in binary representation generator of an integer. Notes ----- @@ -2169,27 +2155,43 @@ def binary_repr(num, width=None): The two's complement is returned when the input number is negative and width is specified: - >>> np.binary_repr(-3, width=4) - '1101' + >>> np.binary_repr(-3, width=3) + '101' + >>> np.binary_repr(-3, width=5) + '11101' """ - # ' <-- unbreak Emacs fontification - sign = '' - if num < 0: + def warn_if_insufficient(width, binwdith): + if width is not None and width < binwidth: + warnings.warn( + "Insufficient bit width provided. This behavior " + "will raise an error in the future.", DeprecationWarning + ) + + if num == 0: + return '0' * (width or 1) + + elif num > 0: + binary = bin(num)[2:] + binwidth = len(binary) + outwidth = (binwidth if width is None + else max(binwidth, width)) + warn_if_insufficient(width, binwidth) + return binary.zfill(outwidth) + + else: if width is None: - sign = '-' - num = -num + return '-' + bin(-num)[2:] + else: - # replace num with its 2-complement - num = 2**width + num - elif num == 0: - return '0'*(width or 1) - ostr = hex(num) - bin = ''.join([_lkup[ch] for ch in ostr[2:]]) - bin = bin.lstrip('0') - if width is not None: - bin = bin.zfill(width) - return sign + bin + poswidth = len(bin(-num)[2:]) + twocomp = 2**(poswidth + 1) + num + + binary = bin(twocomp)[2:] + binwidth = len(binary) + outwidth = max(binwidth, width) + warn_if_insufficient(width, binwidth) + return '1' * (outwidth - binwidth) + binary def base_repr(number, base=2, padding=0): """ diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py index 3a4c05136..7d12ed466 100644 --- a/numpy/core/tests/test_deprecations.py +++ b/numpy/core/tests/test_deprecations.py @@ -579,14 +579,14 @@ class TestArrayDataAttributeAssignmentDeprecation(_DeprecationTestCase): class TestLinspaceInvalidNumParameter(_DeprecationTestCase): - """Argument to the num parameter in linspace that cannot be + """Argument to the num parameter in linspace that cannot be safely interpreted as an integer is deprecated in 1.12.0. - Argument to the num parameter in linspace that cannot be - safely interpreted as an integer should not be allowed. + Argument to the num parameter in linspace that cannot be + safely interpreted as an integer should not be allowed. In the interest of not breaking code that passes an argument that could still be interpreted as an integer, a - DeprecationWarning will be issued for the time being to give + DeprecationWarning will be issued for the time being to give developers time to refactor relevant code. """ def test_float_arg(self): @@ -594,6 +594,32 @@ class TestLinspaceInvalidNumParameter(_DeprecationTestCase): self.assert_deprecated(np.linspace, args=(0, 10, 2.5)) +class TestBinaryReprInsufficientWidthParameterForRepresentation(_DeprecationTestCase): + """ + If a 'width' parameter is passed into ``binary_repr`` that is insufficient to + represent the number in base 2 (positive) or 2's complement (negative) form, + the function used to silently ignore the parameter and return a representation + using the minimal number of bits needed for the form in question. Such behavior + is now considered unsafe from a user perspective and will raise an error in the future. + """ + + def test_insufficient_width_positive(self): + args = (10,) + kwargs = {'width': 2} + + self.message = ("Insufficient bit width provided. This behavior " + "will raise an error in the future.") + self.assert_deprecated(np.binary_repr, args=args, kwargs=kwargs) + + def test_insufficient_width_negative(self): + args = (-5,) + kwargs = {'width': 2} + + self.message = ("Insufficient bit width provided. This behavior " + "will raise an error in the future.") + self.assert_deprecated(np.binary_repr, args=args, kwargs=kwargs) + + class TestTestDeprecated(object): def test_assert_deprecated(self): test_case_instance = _DeprecationTestCase() diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py index e22a5e193..a43ad96b7 100644 --- a/numpy/core/tests/test_numeric.py +++ b/numpy/core/tests/test_numeric.py @@ -1021,12 +1021,25 @@ class TestBinaryRepr(TestCase): def test_zero(self): assert_equal(np.binary_repr(0), '0') - def test_large(self): - assert_equal(np.binary_repr(10736848), '101000111101010011010000') + def test_positive(self): + assert_equal(np.binary_repr(10), '1010') + assert_equal(np.binary_repr(12522), + '11000011101010') + assert_equal(np.binary_repr(10736848), + '101000111101010011010000') def test_negative(self): assert_equal(np.binary_repr(-1), '-1') - assert_equal(np.binary_repr(-1, width=8), '11111111') + assert_equal(np.binary_repr(-10), '-1010') + assert_equal(np.binary_repr(-12522), + '-11000011101010') + assert_equal(np.binary_repr(-10736848), + '-101000111101010011010000') + + def test_sufficient_width(self): + assert_equal(np.binary_repr(0, width=5), '00000') + assert_equal(np.binary_repr(10, width=7), '0001010') + assert_equal(np.binary_repr(-5, width=7), '1111011') class TestBaseRepr(TestCase): |