Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the math behind * 1233 >> 12 in this code counting decimal digits

I am a bit confused how this short function from the C++ {fmt} library works.

inline std::uint32_t digits10_clz(std::uint32_t n) {
  std::uint32_t t = (32 - __builtin_clz(n | 1)) * 1233 >> 12;
  return t - (n < powers_of_10_u32[t]) + 1;
}

I understand the logic that you can approximate the log10 using log2(__builtin_clz) and that you need to adjust for exact value, but the multiplication is a mystery to me.

like image 226
NoSenseEtAl Avatar asked Dec 13 '17 05:12

NoSenseEtAl


1 Answers

Recall the formula for changing the base of logarithm from b to d is

logdx = logbx / logbd

In our case, b is 2 (binary), and d is 10 (decimal). Hence, you need to divide by log210, which is the same as multiplying by 1/log210, i.e by 0.30102999566.

Now recall that shifting by 12 is the same as dividing by 212, which is 4096. Dividing 1233 by 4096 yields 0.30102539062, which is a pretty good approximation for the denominator in the base change formula.

like image 51
Sergey Kalinichenko Avatar answered Oct 17 '22 12:10

Sergey Kalinichenko