こういう誤差収束を使う方が余裕で速いことが分かりました。
do { unsigned long long q; unsigned long long m; q = 0; m = n; while (m > 0xffffffff) { unsigned long long err; err = (m >> 3) - (m >> 5) + (m >> 7) - (m >> 9); q += err; m -= err * 10; } if (m >= 10) { q += (unsigned long) m / 10; m = (unsigned long) m % 10; } *p++ = m + '0'; n = q; } while (n);
4倍は速いです。でもコードが80バイトも大きくなったので、捨て。