Index: Objects/intobject.c =================================================================== --- Objects/intobject.c (revision 65221) +++ Objects/intobject.c (working copy) @@ -1138,6 +1138,21 @@ return NULL; } +static PyObject * +int_numbits(PyIntObject *v) +{ + long n = v->ob_ival; + long result = 0; + + if (n < 0) + n = -n; + while (n) { + ++result; + n >>= 1; + } + return PyInt_FromLong(result); +} + #if 0 static PyObject * int_is_finite(PyObject *v) @@ -1147,6 +1162,8 @@ #endif static PyMethodDef int_methods[] = { + {"numbits", (PyCFunction)int_numbits, METH_NOARGS, + "Returns the number of binary digits in self."}, {"conjugate", (PyCFunction)int_int, METH_NOARGS, "Returns self, the complex conjugate of any int."}, #if 0 Index: Objects/longobject.c =================================================================== --- Objects/longobject.c (revision 65221) +++ Objects/longobject.c (working copy) @@ -3447,6 +3447,12 @@ return PyInt_FromSsize_t(res); } +static PyObject * +long_numbits(PyLongObject *v) +{ + return PyInt_FromSize_t(_PyLong_NumBits((PyObject *)v)); +} + #if 0 static PyObject * long_is_finite(PyObject *v) @@ -3456,6 +3462,8 @@ #endif static PyMethodDef long_methods[] = { + {"numbits", (PyCFunction)long_numbits, METH_NOARGS, + "Returns the number of binary digits in self."}, {"conjugate", (PyCFunction)long_long, METH_NOARGS, "Returns self, the complex conjugate of any long."}, #if 0 @@ -3472,6 +3480,10 @@ }; static PyGetSetDef long_getset[] = { +/* {"numbits", + (getter)PyLong_NumBits, (setter)NULL, + "number of bits in an integer", + NULL}, */ {"real", (getter)long_long, (setter)NULL, "the real part of a complex number", Index: Lib/test/test_int.py =================================================================== --- Lib/test/test_int.py (revision 65221) +++ Lib/test/test_int.py (working copy) @@ -240,6 +240,21 @@ self.assertEqual(int('2br45qc', 35), 4294967297L) self.assertEqual(int('1z141z5', 36), 4294967297L) + def test_numbits(self): + self.assertEqual((0).numbits(), 0) + self.assertEqual((1).numbits(), 1) + self.assertEqual((-1).numbits(), 1) + self.assertEqual((2).numbits(), 2) + self.assertEqual((-2).numbits(), 2) + for i in [2, 3, 15, 16, 17, 31, 32, 33, 63, 64]: + a = 2**i + self.assertEqual((a-1).numbits(), i) + self.assertEqual((1-a).numbits(), i) + self.assertEqual((a).numbits(), i+1) + self.assertEqual((-a).numbits(), i+1) + self.assertEqual((a+1).numbits(), i+1) + self.assertEqual((-a-1).numbits(), i+1) + def test_intconversion(self): # Test __int__() class ClassicMissingMethods: Index: Lib/test/test_long.py =================================================================== --- Lib/test/test_long.py (revision 65221) +++ Lib/test/test_long.py (working copy) @@ -747,6 +747,22 @@ self.assertRaises(OverflowError, long, float('inf')) self.assertEqual(long(float('nan')), 0L) + def test_numbits(self): + self.assertEqual((0L).numbits(), 0) + self.assertEqual((1L).numbits(), 1) + self.assertEqual((-1L).numbits(), 1) + self.assertEqual((2L).numbits(), 2) + self.assertEqual((-2L).numbits(), 2) + for i in [2, 3, 15, 16, 17, 31, 32, 33, 63, 64, 234]: + a = 2L**i + self.assertEqual((a-1).numbits(), i) + self.assertEqual((1-a).numbits(), i) + self.assertEqual((a).numbits(), i+1) + self.assertEqual((-a).numbits(), i+1) + self.assertEqual((a+1).numbits(), i+1) + self.assertEqual((-a-1).numbits(), i+1) + + def test_main(): test_support.run_unittest(LongTest)