Repository: numpy/numpy

Issue:
Add a bits attribute to np.finfo() (Trac #1288)
_Original ticket http://projects.scipy.org/numpy/ticket/1288 on 2009-11-06 by @astrofrog, assigned to unknown._

The number of bits occupied by an integer type can be found from:

In [6]: np.iinfo(np.int16).bits

Out[6]: 16

but this is not currently possible for floats:

In [7]: np.finfo(np.float32).bits

AttributeError                            Traceback (most recent call  
last)

/Users/tom/<ipython console> in <module>()

AttributeError: 'finfo' object has no attribute 'bits'

Would it be possible to implement this?



Discussion:
Milestone changed to `Unscheduled` by @cournape on 2009-11-27

Sounds reasonable.


Resolving patch:
diff --git a/numpy/core/getlimits.py b/numpy/core/getlimits.py
--- a/numpy/core/getlimits.py
+++ b/numpy/core/getlimits.py
@@ -30,6 +30,8 @@ class finfo(object):
 
     Attributes
     ----------
+    bits : int
+        The number of bits occupied by the type.
     eps : float
         The smallest representable positive number such that
         ``1.0 + eps != 1.0``.  Type of `eps` is an appropriate floating
@@ -157,6 +159,7 @@ def _init(self, dtype):
             setattr(self, word, getattr(machar, word))
         for word in ['tiny', 'resolution', 'epsneg']:
             setattr(self, word, getattr(machar, word).flat[0])
+        self.bits = self.dtype.itemsize * 8
         self.max = machar.huge.flat[0]
         self.min = -self.max
         self.eps = machar.eps.flat[0]
@@ -174,12 +177,12 @@ def __str__(self):
         fmt = (
             'Machine parameters for %(dtype)s\n'
             '---------------------------------------------------------------\n'
-            'precision=%(precision)3s   resolution= %(_str_resolution)s\n'
-            'machep=%(machep)6s   eps=        %(_str_eps)s\n'
-            'negep =%(negep)6s   epsneg=     %(_str_epsneg)s\n'
-            'minexp=%(minexp)6s   tiny=       %(_str_tiny)s\n'
-            'maxexp=%(maxexp)6s   max=        %(_str_max)s\n'
-            'nexp  =%(nexp)6s   min=        -max\n'
+            'precision = %(precision)3s   resolution = %(_str_resolution)s\n'
+            'machep = %(machep)6s   eps =        %(_str_eps)s\n'
+            'negep =  %(negep)6s   epsneg =     %(_str_epsneg)s\n'
+            'minexp = %(minexp)6s   tiny =       %(_str_tiny)s\n'
+            'maxexp = %(maxexp)6s   max =        %(_str_max)s\n'
+            'nexp =   %(nexp)6s   min =        -max\n'
             '---------------------------------------------------------------\n'
             )
         return fmt % self.__dict__
@@ -200,6 +203,8 @@ class iinfo(object):
 
     Attributes
     ----------
+    bits : int
+        The number of bits occupied by the type.
     min : int
         The smallest integer expressible by the type.
     max : int


Test patch:
diff --git a/numpy/core/tests/test_getlimits.py b/numpy/core/tests/test_getlimits.py
--- a/numpy/core/tests/test_getlimits.py
+++ b/numpy/core/tests/test_getlimits.py
@@ -42,6 +42,19 @@ def test_singleton(self,level=2):
         ftype2 = finfo(longdouble)
         assert_equal(id(ftype), id(ftype2))
 
+class TestFinfo(TestCase):
+    def test_basic(self):
+        dts = list(zip(['f2', 'f4', 'f8', 'c8', 'c16'],
+                       [np.float16, np.float32, np.float64, np.complex64,
+                        np.complex128]))
+        for dt1, dt2 in dts:
+            for attr in ('bits', 'eps', 'epsneg', 'iexp', 'machar', 'machep',
+                         'max', 'maxexp', 'min', 'minexp', 'negep', 'nexp',
+                         'nmant', 'precision', 'resolution', 'tiny'):
+                assert_equal(getattr(finfo(dt1), attr),
+                             getattr(finfo(dt2), attr), attr)
+        self.assertRaises(ValueError, finfo, 'i4')
+
 class TestIinfo(TestCase):
     def test_basic(self):
         dts = list(zip(['i1', 'i2', 'i4', 'i8',
@@ -49,8 +62,9 @@ def test_basic(self):
                   [np.int8, np.int16, np.int32, np.int64,
                    np.uint8, np.uint16, np.uint32, np.uint64]))
         for dt1, dt2 in dts:
-            assert_equal(iinfo(dt1).min, iinfo(dt2).min)
-            assert_equal(iinfo(dt1).max, iinfo(dt2).max)
+            for attr in ('bits', 'min', 'max'):
+                assert_equal(getattr(iinfo(dt1), attr),
+                             getattr(iinfo(dt2), attr), attr)
         self.assertRaises(ValueError, iinfo, 'f4')
 
     def test_unsigned_max(self):