summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/numeric.py90
-rw-r--r--numpy/core/tests/test_deprecations.py34
-rw-r--r--numpy/core/tests/test_numeric.py19
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):