Say you start with two Int16’s. Any addition would result in an Int17. Adding a pair of those together would result in an Int18, and so forth.
You’d blow past Int64 in no time.
Not really. You only need to preserve according to the msb of each number. If you are adding 0(Int18)+1(Int18), you don't need 1(Int36) anymore than you need 1(Int18) or even 1(Int1).
No, you’d need an Int19. We were talking about statically typed languages, so you need to decide the type at compile-time. If you add two UInt16’s they could both contain up to 0xFFFF, you need 17 bits to store that answer. Basically, with every addition you need 1 more bit than the largest of the two (types, not values) you are adding together to prevent a potential overflow. It’s even worse for multiplication.
(Note that I'm not too clear how valuable this would be. Just asking why that isn't a valid path.)
No, that's completely false. You don't need an Int19 but an Int1.
class bignum {
private:
digit_t *limbs;
public:
bignum(int val);
~bignum();
bignum operator +(const bignum &rhs);
...
};Not so for loops and accumulator constructs.
What is the width of `i` in:
foo(int count) {
int i = 0;
for (int j = 0; j < count; j++) {
i = i + i;
}
}i = 0 implies that i = 0 + 0 = 0; so the loop doesn’t evolve, and the whole thing can be optimized to just i = 0.
For i=1, the loop simplifies to 2^count and a count-length type, which is the point I think you wanted.
The problem you can then run into is that a mathematical operation can OOM
You need some numeric accident involving a higher power operator like exponentiation.
In TXR Lisp I made exponentiation n-ary: you can do (expt x y z ...).
The associativity is right to left: it means
...
z
y
x
rather than the less useful cumulative exponentiation of the same base: yz...
x
which can easily be obtained as (expt x (* y z ..)).So, anyway, if you apply expt to small list of small operands, you can cons up a big number in rather a hurry.
If it is important to prevent a problem like this, a limit can be imposed on bignums (say, large enough for common cryptography to still work).
I gotta disagree on perl, though, even though it can represent numbers outside of the range of a double, it can't manipulate them without converting them into doubles.
I'm curious which dynamic language reallocates to store larger integers? All of the dynamic languages that I'm familiar with simply store numbers as doubles, with variable width integers being handled by opt-in types.