Skip to content

Commit f3bd8f4

Browse files
mahdisarikhanistormoficeleios
authored
Add approximate counting algorithm in C (#844)
* Add approximate counting algorithm in C * Fix typo Co-authored-by: stormofice <58337328+stormofice@users.noreply.github.com> Co-authored-by: stormofice <58337328+stormofice@users.noreply.github.com> Co-authored-by: James Schloss <jrs.schloss@gmail.com>
1 parent 39f8c1c commit f3bd8f4

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

contents/approximate_counting/approximate_counting.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,8 @@ As we do not have any objects to count, we will instead simulate the counting wi
360360
{% method %}
361361
{% sample lang="jl" %}
362362
[import, lang:"julia"](code/julia/approximate_counting.jl)
363+
{% sample lang="c" %}
364+
[import, lang:"c"](code/c/approximate_counting.c)
363365
{% sample lang="cpp" %}
364366
[import, lang:"cpp"](code/c++/approximate_counting.cpp)
365367
{% sample lang="python" %}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#include <assert.h>
2+
#include <math.h>
3+
#include <stdio.h>
4+
#include <stdlib.h>
5+
#include <time.h>
6+
7+
// This function returns a pseudo-random number between 0 and 1
8+
double drand()
9+
{
10+
return (double)rand() / RAND_MAX;
11+
}
12+
13+
// This function takes
14+
// - v: value in register
15+
// - a: a scaling value for the logarithm based on Morris's paper
16+
// It returns the approximate count
17+
double n(double v, double a)
18+
{
19+
return a * (pow(1 + 1 / a, v) - 1);
20+
}
21+
22+
// This function takes
23+
// - v: value in register
24+
// - a: a scaling value for the logarithm based on Morris's paper
25+
// It returns a new value for v
26+
double increment(double v, double a)
27+
{
28+
// delta is the probability of incrementing our counter
29+
double delta = 1 / (n(v + 1, a) - n(v, a));
30+
31+
if (drand() <= delta) {
32+
return v + 1;
33+
}
34+
return v;
35+
}
36+
37+
// This function simulates counting and takes
38+
// - n_items: number of items to count and loop over
39+
// - a: a scaling value for the logarithm based on Morris's paper
40+
// It returns n(v, a), the approximate count
41+
double approximate_count(size_t n_items, double a)
42+
{
43+
int v = 0;
44+
for (size_t i = 0; i < n_items; ++i) {
45+
v = increment(v, a);
46+
}
47+
48+
return n(v, a);
49+
}
50+
51+
// This function takes
52+
// - n_trials: the number of counting trials
53+
// - n_items: the number off items to count
54+
// - a: a scaling value for the logarithm based on Morris's paper
55+
// - threshold: the maximum percent error allowed
56+
// It terminates the program on failure
57+
void test_approximation_count(size_t n_trials, size_t n_items, double a,
58+
double threshold)
59+
{
60+
double sum = 0.0;
61+
for (size_t i = 0; i < n_trials; ++i) {
62+
sum += approximate_count(n_items, a);
63+
}
64+
double avg = sum / n_trials;
65+
66+
assert(fabs((avg - n_items) / n_items) < threshold);
67+
}
68+
69+
int main()
70+
{
71+
srand(time(NULL));
72+
73+
printf("Counting Tests, 100 trials\n");
74+
printf("testing 1000, a = 30, 1%% error\n");
75+
test_approximation_count(100, 1000, 30, 0.1);
76+
printf("testing 12345, a = 10, 1%% error\n");
77+
test_approximation_count(100, 12345, 10, 0.1);
78+
printf("testing 222222, a = 0.5, 10%% error\n");
79+
test_approximation_count(100, 222222, 0.5, 0.2);
80+
81+
return 0;
82+
}

0 commit comments

Comments
 (0)