Problem (legend of the inventor of chess). One grain of wheat on the first square, two on the second, four on the third, doubling each square. How much wheat is on the board?

Answer. grains, exactly ULLONG_MAX. At about 50 mg per grain that is roughly tonnes, over a thousand years of today’s world wheat harvest (about tonnes a year).

Doubling factValue
square grains
first squares (always one less than the next square)
second half of the board vs the first times as much
so , quick estimate (true )
lily pad doubling daily, lake full on day 48half full on day 47
fold a 0.1 mm sheet 42 times km, beyond the Moon
doubling time at growth rate periods (rule of 70)

Overflow in practice

The board is the natural boundary of 64-bit integers, which is why the puzzle doubles as a checklist of integer pitfalls.

ExpressionProblemFix
1 << 40int shift, overflow1LL << 40
1ULL << 64shift by the full width is undefinedspecial-case , or ~0ULL
1LL << 63sign bit; before C++20 undefineduse ull, or LLONG_MIN
(ll)pow(10, 18)double result may be after truncationinteger loop, or llround
a * b with overflows ll__int128, or __builtin_mul_overflow
sum += x over values up to overflows at check the bound first, or saturate
a * b % m with product overflows before %(i128)a * b % m
ull grainsUpTo(int k) { return k >= 64 ? ~0ULL : (1ULL << k) - 1; }   // squares 1..k, k in [0, 64]
 
ll powSat(ll b, int e, ll cap) {                     // min(b^e, cap) for b >= 1, without overflow
    ll r = 1;
    while (e--) { if (r > cap / b) return cap; r *= b; }
    return r;
}
 
ll mulSat(ll a, ll b) {                              // a * b clamped to [LLONG_MIN, LLONG_MAX]
    ll r;
    if (!__builtin_mul_overflow(a, b, &r)) return r;
    return ((a < 0) ^ (b < 0)) ? LLONG_MIN : LLONG_MAX;
}