An integer represents a quantity that exists independently of the format in which it is expressed. For example, an integer might usually be expressed in base 10, but could also be expressed in binary, hexadecimal, Roman numerals, or other format. The number of characters needed to represent a given quantity among those various formats may differ. Therefore, an integer does not have an intrinsic length.
If you have an integer represented by a variable, n, and it might be positive or negative, you can simply do something like this to get its number of digits in its base 10 representation:
For other bases or representations, adjust your strategy accordingly.
That is better than making a fundamental change to Python’s int type.
The simplest way to solve the problem is: len(str(555)). It’s simple, it’s correct, it’s faster even for short inputs, and it’s much faster for large inputs. Sometimes people object that this is wastefully creating a temporary string, but there will be a whole bunch of temporary integer objects anyway.
The number of digits can also be realized as a base-10 logarithm, as Barry shows. It’s even faster, and scarcely even cares about the size of the input - because it doesn’t have to divide repeatedly; it can basically use the base-256 length of the number in its raw binary form, and multiply by a constant (after adjusting for the first few bits that actually make a difference to the logarithm represented as a floating-point value).
This sometimes makes people feel uneasy because of some intuition about floating-point accuracy. But I’ve yet to be shown a case where it gets the wrong result - at least for suitably large values. Negative values and 0 need to be special-cased because the (real-valued) logarithm is not well defined there, and 1 has a logarithm of 0 rather than the required 1 (regardless of base).
I don’t agree, and I don’t see why you imagine so. Aside from the fact that making a string first is easy, this simply isn’t a common task outside the world of homework and tutorials.
An int is treated as a fixed width container of flags when performing embedded work in C. Perform bitwise operations on integers which are the settings to processor registers for setting up peripherals, each bit of the register is a different setting.
That definitely is not a Python integer, though. If you want that sort of integer, numpy has a set of defined-width types, and Python’s own struct module can pack and unpack them. But an integer, in Python, has no defined width and will not wrap around at any point.
There are many ways you could define the “length” of a number (eg the number of bytes required to represent it in base 256, the number of digits required to represent it in base 10, the bit length - that one’s available as a method), and none of them allow for the concept of a fixed width regardless of the value.
Yep. What I should have said was: Since there’s so many options, you need to choose, which is why we have “bit length” saying so explicitly in the name. So if someone wants to pitch a different definition of “length”, it would want to be another method like that, rather than being __len__, since there’s no single logical definition of the “length” of an integer.
(Also, when I said that “none of them allow for a fixed width”, what I meant was that there’s no way to say that the integer 1 is part of a 16-flag collection or a 32-flag collection; it’s always implicitly carrying an infinite number of additional zero flags.)
I think @Rosuav already mentioned most things regarding the multiple possible interpretations of “integer length” so I won’t rehash that, but if you want to treat integers as “flag” containers in Python you can get their length using the int.bit_length() method.
Heh. Locally when I did performance testing, I tried math.ceil rather than adding one to the math.floor result. But that’s wrong for every integer power of 10 So that’s another reason not to do things that way, I suppose. And actually it’s probably pretty easy to construct examples regardless of the implementation details. I clearly just haven’t been looking hard enough for examples
The more interesting thing to me is that math.log10 is able to work on integers beyond the range of the double type.
Would it be helpful for students to have such a builtin? If this existed as builtin (for instance as a function on integers called “decimal_length” similar to “bit_length”), and I was teaching your class, I would consider explicitly forbidding students from using the builtin. Not using the builtin could be considered “more helpful” since it would stimulate students to come up with their own methods and think about the problem. Right?
Why do you need to know this number? If it’s “because the assignment asked for it”, then probably the point of the assignment is for you to be able to write the algorithm. For real-world programs, it’s hard to find a situation where we would actually care.
Wait, do they not use the entire memory block for each “digit” (except perhaps the most significant one which might need a sign bit)? And do they really not use 64-bit elements in 64-bit builds?
You can of course define your own object with this behaviour
value = abs(self)
length = 0
value = value//10
length += 1
But I would not recommend it - The len in Python is defined as the number of items (Python objects) in a collection. An int is not a collection in the standard Python definition. Your object would behave in unexpected ways.