こういう誤差収束を使う方が余裕で速いことが分かりました。
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バイトも大きくなったので、捨て。