Each register carries a noisy guess at the cardinality. HyperLogLog combines them with a harmonic mean and a correction constant to produce one raw estimate. Today you compute that formula.
Compute the raw cardinality estimate from the registers using the harmonic mean with the alpha constant.
Each register’s maximum rank is itself a rough, high-variance estimate of the cardinality. HyperLogLog tames that noise by combining all m registers with a harmonic mean, which is far more robust to a single unusually large register than an ordinary average would be. Concretely: sum 2^(-register) over every register, divide m^2 by that sum, and scale by a bias constant alpha that depends on m (0.673 for 16 registers). That is the raw estimate E.
Empty registers - those still at zero - contribute 2^0 = 1 each to the sum, so a mostly-empty sketch has a large denominator and a small estimate. Here ten of the sixteen registers are still zero, which is a warning sign: this many empties means very few distinct items have been seen, and the raw formula is known to be biased in exactly that regime. The raw estimate of about 14.66 badly overshoots the true 8. The formula is right for large cardinalities but needs a correction when the sketch is nearly empty, which is next.
func (h *HLL) rawEstimate() float64 {sum := 0.0for _, v := range h.registers { sum += math.Pow(2, -float64(v)) }m := float64(len(h.registers))return alpha(len(h.registers)) * m * m / sum // alpha(16) = 0.673}