<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lucas Lee</title>
    <description>The latest articles on DEV Community by Lucas Lee (@lucasleetech).</description>
    <link>https://dev.to/lucasleetech</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3710185%2F713fa44d-3632-4834-81dc-c40c73582f3c.jpg</url>
      <title>DEV Community: Lucas Lee</title>
      <link>https://dev.to/lucasleetech</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lucasleetech"/>
    <language>en</language>
    <item>
      <title>Counting Billions of Unique Items with the Magic of HyperLogLog</title>
      <dc:creator>Lucas Lee</dc:creator>
      <pubDate>Sun, 25 Jan 2026 14:22:13 +0000</pubDate>
      <link>https://dev.to/lucasleetech/counting-billions-of-unique-items-with-the-magic-of-hyperloglog-2j8a</link>
      <guid>https://dev.to/lucasleetech/counting-billions-of-unique-items-with-the-magic-of-hyperloglog-2j8a</guid>
      <description>&lt;h2&gt;
  
  
  1. Introduction: Starting with a Classic Interview Question
&lt;/h2&gt;

&lt;p&gt;In the realm of massive data processing, there is a classic interview question that has been asked &lt;em&gt;ad nauseam&lt;/em&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Given 1 billion IP addresses and a memory limit of only 1MB, how do you calculate the number of unique IPs (Cardinality Estimation)?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you attempt to use &lt;code&gt;std::set&lt;/code&gt; or &lt;code&gt;HashSet&lt;/code&gt;, simply storing 1 billion IPs will instantly exhaust your memory. Even using a &lt;strong&gt;Bitmap&lt;/strong&gt; offers insufficient compression if the data is sparse.&lt;/p&gt;

&lt;p&gt;Today, let's talk about &lt;strong&gt;HyperLogLog (HLL)&lt;/strong&gt;. It is a probabilistic algorithm that can estimate the cardinality of datasets in the billions with a standard error of less than 2%, all while using just a few kilobytes of memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The Intuition: The "Black Magic" of Coin Flipping
&lt;/h2&gt;

&lt;p&gt;Imagine you are playing a simple coin-tossing game: &lt;strong&gt;Tails is 0, Heads is 1&lt;/strong&gt;. The rule is simple: you keep flipping the coin until you get the &lt;strong&gt;first Heads (1)&lt;/strong&gt;, at which point this round of the game ends.&lt;/p&gt;

&lt;p&gt;According to probability theory, we observe the following phenomena:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The probability of getting Heads on the &lt;strong&gt;1st try&lt;/strong&gt; is &lt;strong&gt;1/2&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The probability of getting Heads after &lt;strong&gt;2 consecutive&lt;/strong&gt; Tails is &lt;strong&gt;1/8&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The probability of getting Heads after &lt;strong&gt;n consecutive&lt;/strong&gt; Tails is &lt;strong&gt;1 / 2^(n+1)&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;There is a core logic hidden here:&lt;/strong&gt; If you observe an extremely rare sequence—for example, flipping 20 consecutive Tails before seeing a Heads (a probability of roughly one in a million)—your intuition tells you: &lt;strong&gt;to encounter such a "stroke of luck," you must have been silently attempting this millions of times in the background.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We transform this intuition into an inference formula:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the maximum length of "consecutive Tails" observed in our experiment is &lt;strong&gt;n&lt;/strong&gt;, we can boldly speculate that approximately &lt;strong&gt;2^(n+1)&lt;/strong&gt; rounds of experiments have been conducted.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is a "reasonable estimate," not an exact value. Just as winning the lottery once doesn't prove you are a billionaire, HyperLogLog uses this probability distribution to make an &lt;strong&gt;approximate estimation&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. From Coin Flips to Bitstreams: The Mathematical Foundation
&lt;/h2&gt;

&lt;p&gt;In the computer world, everything is bits (0s and 1s). We can cleverly view the binary representation of data as the result of a series of "coin flips": &lt;strong&gt;0 represents Tails, 1 represents Heads.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We define the rule: &lt;strong&gt;Scan from right to left (low bit to high bit) until the first &lt;code&gt;1&lt;/code&gt; (Heads) is encountered. This ends the "game."&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sequence &lt;code&gt;...01&lt;/code&gt;&lt;/strong&gt;: Heads on the first try. Game over. Value = 1.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sequence &lt;code&gt;...010&lt;/code&gt;&lt;/strong&gt;: First Tails, second Heads. Value = 2. (Note: Bits after the first &lt;code&gt;1&lt;/code&gt; are ignored in this probabilistic model).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sequence &lt;code&gt;...1000&lt;/code&gt;&lt;/strong&gt;: Three Tails, then Heads. Value = 4.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sequence &lt;code&gt;...1&lt;/code&gt; followed by n &lt;code&gt;0&lt;/code&gt;s&lt;/strong&gt;: Indicates &lt;strong&gt;n&lt;/strong&gt; consecutive Tails.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Now, let's solve a probability problem:&lt;/strong&gt; In a randomly distributed bitstream, what is the probability of needing &lt;strong&gt;n&lt;/strong&gt; consecutive &lt;code&gt;0&lt;/code&gt;s to end the game? The answer is simple: &lt;strong&gt;1 / 2^(n+1)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reverse Thinking:&lt;/strong&gt; Suppose I have a pile of binary strings, and the &lt;strong&gt;longest run of consecutive zeros&lt;/strong&gt; I observe is &lt;strong&gt;n&lt;/strong&gt;. Based on our previous conclusion, we can infer: &lt;strong&gt;to stumble upon this "miracle," I must have looked at approximately 2^(n+1) distinct binary strings.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is the core principle of HyperLogLog:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Observe Extremes:&lt;/strong&gt; Instead of recording the data itself, we only record the &lt;strong&gt;maximum length of consecutive zeros&lt;/strong&gt; observed across all data (denoted as &lt;strong&gt;ρ&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infer Cardinality:&lt;/strong&gt; Use this maximum length to back-calculate the number of unique elements (cardinality).&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; If you see &lt;strong&gt;n&lt;/strong&gt; consecutive &lt;strong&gt;0&lt;/strong&gt;s, it suggests that approximately &lt;strong&gt;2^(n+1)&lt;/strong&gt; distinct items have passed through.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  4. Engineering Challenges: From Theory to Reality
&lt;/h2&gt;

&lt;h3&gt;
  
  
  4.1 Challenge 1: Breaking Patterns (Why We Need Hashing)
&lt;/h3&gt;

&lt;p&gt;The mathematical derivation above relies on a &lt;strong&gt;"Strong Assumption"&lt;/strong&gt;: the probability of &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt; appearing in the bitstream must be strictly &lt;strong&gt;1:1&lt;/strong&gt;, and bits must be independent. In other words, it must be a &lt;strong&gt;"perfectly fair coin."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;However, in real-world engineering, raw data is often extremely "unfair." Imagine counting a sequence of User IDs: &lt;code&gt;1000&lt;/code&gt;, &lt;code&gt;1001&lt;/code&gt;, &lt;code&gt;1002&lt;/code&gt;... Their binary representations are almost identical in their long prefixes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;1000&lt;/code&gt; -&amp;gt; &lt;code&gt;...001111101000&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;1001&lt;/code&gt; -&amp;gt; &lt;code&gt;...001111101001&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If these IDs naturally contain many consecutive zeros (e.g., low-value IDs), HLL will hallucinate, believing it has observed a "rare event" with a tiny probability, leading to an astronomically incorrect estimate.&lt;/p&gt;

&lt;p&gt;To fix this loophole, we must introduce a &lt;strong&gt;Hash Function&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;While we won't dive deep into hash implementation here, remember its core mission: &lt;strong&gt;to "scatter" patterned data into a uniformly distributed, randomly perturbed bitstream.&lt;/strong&gt; In the world of HyperLogLog, hashing is not for encryption, but to ensure every "coin" we flip is "fair."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4jzlk0kkfkiszhka823q.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4jzlk0kkfkiszhka823q.jpg" alt="WHY HASH" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2 Challenge 2: Eliminating the "Outlier" Bias
&lt;/h3&gt;

&lt;p&gt;Even with a fair coin, probability still allows for extreme cases. What if you are incredibly lucky and flip 30 consecutive &lt;code&gt;0&lt;/code&gt;s on your very first try?&lt;/p&gt;

&lt;p&gt;The algorithm would naively assume you have 1 billion items, when in reality, you inserted just one. This deviation caused by a single point of failure is catastrophic in statistics.&lt;/p&gt;

&lt;p&gt;To bring the results back to rationality, HyperLogLog introduces two major "noise reduction" tools: &lt;strong&gt;Bucketing&lt;/strong&gt; and the &lt;strong&gt;Harmonic Mean&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  4.2.1 Bucketing: Don't Put All Your Eggs in One Basket
&lt;/h4&gt;

&lt;p&gt;Since one person's "luck" is unreliable, we look at the average level of a crowd.&lt;/p&gt;

&lt;p&gt;We split the 64-bit hash value into two parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High b bits (Bucket Index):&lt;/strong&gt; Determines which "room" the data goes to. If &lt;strong&gt;b = 10&lt;/strong&gt;, we have &lt;strong&gt;m = 2^10 = 1024&lt;/strong&gt; independent buckets (Registers).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remaining bits (Coin Flip):&lt;/strong&gt; Used to record the maximum run of consecutive zeros seen &lt;em&gt;within that specific bucket&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This way, one "giant guess" is broken down into 1024 "independent small guesses." Even if one bucket records an anomalously high value due to sheer luck, it only affects 1/1024th of the decision weight, preventing it from skewing the overall picture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fucp396ce9iu152mh53h7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fucp396ce9iu152mh53h7.jpg" alt="WHY BUCKETING" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  4.2.2 Harmonic Mean: A Dimensional Strike on Outliers
&lt;/h4&gt;

&lt;p&gt;When summarizing the results of these 1024 buckets, using a simple &lt;strong&gt;Arithmetic Mean&lt;/strong&gt; is dangerous.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Suppose 1023 buckets have a value of &lt;code&gt;1&lt;/code&gt;, but one bucket—due to extreme luck—has a value of &lt;code&gt;100&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Arithmetic Mean:&lt;/strong&gt; (1 * 1023 + 100) / 1024 ≈ 1.1.
This looks stable, right? Wrong. HLL's estimation is &lt;strong&gt;exponential&lt;/strong&gt; (2^R). The difference between &lt;strong&gt;2^1&lt;/strong&gt; and &lt;strong&gt;2^100&lt;/strong&gt; is astronomical.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To solve this, HLL uses the &lt;strong&gt;Harmonic Mean&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Estimate H = m / Σ(1 / 2^R_i)&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;(Where m is the number of buckets, and R_i is the value in each bucket)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Harmonic Mean has a crucial property: &lt;strong&gt;It is very insensitive to large outliers (the "nouveau riche") but sensitive to small values.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0gb1cm3d16bvhhkdfyl9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0gb1cm3d16bvhhkdfyl9.jpg" alt="WHY HARMONIC MEAN" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By doing this, extreme values generated by accidental "good luck" are effectively smoothed out, allowing the estimate to land firmly near the true cardinality.&lt;/p&gt;

&lt;h4&gt;
  
  
  4.2.3 Correction Parameters: Eliminating "Inherent Bias"
&lt;/h4&gt;

&lt;p&gt;Even with Bucketing and Harmonic Mean, mathematicians discovered that the raw HLL formula still has a &lt;strong&gt;systematic inherent bias&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Simply put, the algorithm logically tends to "overestimate" or "underestimate" the true cardinality depending on the number of buckets &lt;strong&gt;m&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To make the estimate approximate the true value as closely as possible, HLL introduces a &lt;strong&gt;correction constant α_m&lt;/strong&gt;. This constant varies with bucket precision:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When &lt;strong&gt;m = 16&lt;/strong&gt;, &lt;strong&gt;α_m = 0.673&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;When &lt;strong&gt;m = 32&lt;/strong&gt;, &lt;strong&gt;α_m = 0.697&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;When &lt;strong&gt;m ≥ 128&lt;/strong&gt;, &lt;strong&gt;α_m&lt;/strong&gt; stabilizes at: &lt;strong&gt;0.7213 / (1 + 1.079 / m)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The number &lt;code&gt;0.7213 / (1 + 1.079 / m)&lt;/code&gt; you see in the code acts like the final &lt;strong&gt;"Zero Calibration"&lt;/strong&gt; on a precision scale. Without it, the entire error curve of HLL would be shifted.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Concrete Implementation
&lt;/h2&gt;

&lt;p&gt;When implementing HyperLogLog, we need to focus on two engineering details: &lt;strong&gt;Efficient Bitwise Operations&lt;/strong&gt; and &lt;strong&gt;Small Range Correction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core Implementation Highlights:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Hardware Acceleration:&lt;/strong&gt; We use the GCC builtin &lt;code&gt;__builtin_ctzll&lt;/code&gt;. This invokes CPU-level instructions (like &lt;code&gt;BSF&lt;/code&gt; or &lt;code&gt;TZCNT&lt;/code&gt; on x86) to count trailing zeros, which is significantly faster than writing a loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory Efficiency:&lt;/strong&gt; Each Register only needs 8 bits (&lt;code&gt;uint8_t&lt;/code&gt;) because the run of consecutive zeros in a 64-bit integer cannot exceed 64. With 1024 buckets, the entire data structure takes up just &lt;strong&gt;1 KB&lt;/strong&gt; of memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Linear Counting Correction:&lt;/strong&gt; Probabilistic algorithms have higher error rates when data volume is extremely small (buckets aren't full yet). Therefore, when the estimate is low, we switch to &lt;strong&gt;Linear Counting&lt;/strong&gt;, using the ratio of empty buckets to calculate cardinality, ensuring accuracy across the full range.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdint.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;math.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// Precision parameter k (Number of buckets = 2^10 = 1024)&lt;/span&gt;
&lt;span class="cp"&gt;#define HLL_PRECISION 10
#define HLL_REGISTERS (1 &amp;lt;&amp;lt; HLL_PRECISION)
#define HLL_MASK (HLL_REGISTERS - 1)
&lt;/span&gt;
&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;registers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;HLL_REGISTERS&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;HyperLogLog&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Simple 64-bit Hash Function (MurmurHash3 mixing part)
 * In production, use full MurmurHash3 or CityHash/FarmHash.
 */&lt;/span&gt;
&lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="nf"&gt;hash_64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x12345678abcdefLL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;^=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mh"&gt;0xbf58476d1ce4e5b9LL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;^=&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Get the position of the first '1' (ρ value)
 * Discard bucket bits, count trailing zeros in the remaining bits.
 */&lt;/span&gt;
&lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="nf"&gt;get_rho&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HLL_PRECISION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;HLL_PRECISION&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Use builtin to count trailing zeros. +1 implies 1-based index of first '1'&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;__builtin_ctzll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Initialize: Zero out all registers&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;hll_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HyperLogLog&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;hll&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;memset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hll&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;registers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HLL_REGISTERS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Add element: Update the max ρ value for the corresponding bucket&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;hll_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HyperLogLog&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;hll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;uint64_t&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hash_64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;HLL_MASK&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Extract low bits for bucket index&lt;/span&gt;
    &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;rho&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_rho&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rho&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hll&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;registers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;hll&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;registers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rho&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Estimate Cardinality: Harmonic Mean + Bias Correction&lt;/span&gt;
&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;hll_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HyperLogLog&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;hll&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HLL_REGISTERS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// αm correction coefficient&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;alpha_m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;7213&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;07&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;HLL_REGISTERS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Calculate 1 / 2^R[i]&lt;/span&gt;
        &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1ULL&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;hll&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;registers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;alpha_m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Small Range Correction (Linear Counting):&lt;/span&gt;
    &lt;span class="c1"&gt;// If estimate &amp;lt; 2.5 * m, correct using empty buckets ratio&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;estimate&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;zeros&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;HLL_REGISTERS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hll&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;registers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;zeros&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zeros&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;estimate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;HyperLogLog&lt;/span&gt; &lt;span class="n"&gt;hll&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;hll_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;hll&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Simulating insertion of 100,000 unique elements...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="n"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"element_%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;hll_add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;hll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Actual Count:    100000&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Estimated Count: %.2f&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hll_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;hll&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error Rate:      %.2f%%&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fabs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hll_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;hll&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Running Result:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F89abvg2f97h9d1mimzn2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F89abvg2f97h9d1mimzn2.png" alt="REUNNING RESULT" width="800" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Conclusion: A Romantic Symphony of Math, Engineering, and AI
&lt;/h2&gt;

&lt;p&gt;The somewhat eccentric name "HyperLogLog" actually inscribes a trilogy of algorithmic evolution, much like a grand symphony:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Log:&lt;/strong&gt; The core rhythm. The algorithm captures the bit-length &lt;strong&gt;ρ&lt;/strong&gt; of consecutive zeros, mapping a massive cardinality to an elegant logarithmic scale.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LogLog:&lt;/strong&gt; The bridge. In 2003, Philippe Flajolet proved that one could glimpse the contours of massive data using minimal space.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hyper:&lt;/strong&gt; The final movement. In 2007, the introduction of the harmonic mean and bias correction pushed precision to "Hyper" limits.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The key to solving engineering bottlenecks is often not "brute force computing," but profound "mathematical models."&lt;/strong&gt; This philosophy of "governing the concrete with the abstract" continues to shine brightly today in AI parameter compression and high-efficiency retrieval.&lt;/p&gt;

&lt;p&gt;From a random game of coin tossing to estimating the cardinality of billions of data points, HyperLogLog perfectly illustrates the ultimate romance of computer science: &lt;strong&gt;Using a square inch of memory to contain a universe of information; trading the "fuzziness" of probability for the "pinnacle" of performance.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A good engineer writes bug-free code; a distinguished engineer leverages the beauty of mathematics to touch the physical limits of the machine.&lt;/p&gt;

</description>
      <category>database</category>
      <category>programming</category>
      <category>datascience</category>
    </item>
  </channel>
</rss>
