5 ms·
Here's one interesting application of a digit-count function. The naive implementation of an integer-to-string conversion involves writing the number backwards
by spatulon 5y ago
Here's one interesting application of a digit-count function.
The naive implementation of an integer-to-string conversion involves writing the number backwards, starting from the least significant digit, and then reversing the string at the end.
In a 2017 talk titled "Fastware"[1], Andrei Alexandrescu showed that it's faster to start by counting the number of digits you're going to print, and then you can print by working backwards from the least significant digit. It comes out in the correct order without any need to reverse at the end.
His implementation of the digit count was itself interesting, since it does 4 comparisons per loop and then a divide by 10000, instead of the naive single comparison and divide by 10.
uint32_t digits10(uint64_t v) {
uint32_t result = 1;
for (;;) {
if (v < 10) return result;
if (v < 100) return result + 1;
if (v < 1000) return result + 2;
if (v < 10000) return result + 3;
v /= 10000U;
result += 4;
}
}
IIRC, his insight was that smaller numbers tend to occur more often in the real world, so most calls to this function will not end up doing any divisions.
[1] https://www.youtube.com/watch?v=o4-CwDo2zpg https://www.youtube.com/watch?v=o4-CwDo2zpg
- rajnathani 5y agoThere are so many branches for the processor to evaluate in such approaches. The linked article does it without any branches (no if condition).
- Bayart 5y agoThat's clever. A uint64 doesn't have more that 20 digits, so I'm guessing returning a uint8 over a uint32 might be better in memory-bound cases.
- vlovich123 5y agoNo, it really wouldn’t matter in the grand scheme of things, especially since the result will live in a register. Even if spilled to the stack, this one usage isn’t going to matter vs all the other stuff that gets regularly spilled.
- WalterBright 5y ago> Alexei Andrescu Andrei Alexandrescu
- spatulon 5y agoThanks, corrected.
- travisjungroth 5y agoI imagine his code letting out a sigh when it gets to v/= 10000U. "ok, fine..."
- cecilpl2 5y agoWhy wouldn't you unroll the entire loop so no divisions are ever required?
- mhh__ 5y agoCode density
- pkaye 5y agoAlso most compilers can optimize the divide by constant to a multiply and shift which are much faster than a divide.