Skip to content

Commit c811056

Browse files
committed
Add C# implementation for the approximate counting algorithm
1 parent cc457b9 commit c811056

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

contents/approximate_counting/approximate_counting.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,8 @@ As we do not have any objects to count, we will instead simulate the counting wi
362362
[import, lang:"julia"](code/julia/approximate_counting.jl)
363363
{% sample lang="cpp" %}
364364
[import, lang:"cpp"](code/c++/approximate_counting.cpp)
365+
{% sample lang="cs" %}
366+
[import, lang:"csharp"](code/csharp/ApproximateCounting.cs)
365367
{% endmethod %}
366368

367369
### Bibliography
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using System;
2+
3+
namespace ApproximateCounting
4+
{
5+
class ApproximateCounting
6+
{
7+
static readonly Random Rng = new();
8+
9+
// This function takes
10+
// - v: value in register
11+
// - a: a scaling value for the logarithm based on Morris's paper
12+
// It returns n(v,a), the approximate count
13+
static double N(int v, double a)
14+
{
15+
return a * Math.Pow(1 + 1 / a, v - 1);
16+
}
17+
18+
// This function takes
19+
// - v: value in register
20+
// - a: a scaling value for the logarithm based on Morris's paper
21+
// It returns a new value for v
22+
static int Increment(int v, double a)
23+
{
24+
var delta = 1 / (N(v + 1, a) - N(v, a));
25+
26+
if (Rng.NextDouble() <= delta)
27+
return v + 1;
28+
else
29+
return v;
30+
}
31+
32+
// This simulates counting and takes
33+
// - noItems: number of items to count and loop over
34+
// - a: a scaling value for the logarithm based on Morris's paper
35+
// It returns n(v,a), the approximate count
36+
static double ApproximateCount(int noItems, double a)
37+
{
38+
var v = 0;
39+
for (var i = 0; i < noItems; i++)
40+
{
41+
v = Increment(v, a);
42+
}
43+
return N(v, a);
44+
}
45+
46+
// This function takes
47+
// - noTrials: the number of counting trials
48+
// - noItems: the number of items to count to
49+
// - a: a scaling value for the logarithm based on Morris's paper
50+
// - threshold: the maximum percent error allowed
51+
// It returns a "pass" / "fail" test value
52+
static string TextApproximateCount(int noTrials, int noItems, double a, double threshold)
53+
{
54+
var sum = 0.0;
55+
for (var i = 0; i < noTrials; i++)
56+
sum += ApproximateCount(noItems, a);
57+
58+
var avg = sum / noTrials;
59+
60+
return Math.Abs((avg - noItems) / noItems) < threshold ? "pass" : "fail";
61+
}
62+
63+
static void Main()
64+
{
65+
Console.WriteLine("Counting Tests, 100 trials");
66+
Console.WriteLine($"Testing 1,000, a = 30, 1% error : {TextApproximateCount(100, 1_000, 30, 0.1)}");
67+
Console.WriteLine($"Testing 12,345, a = 10, 1% error : {TextApproximateCount(100, 12_345, 10, 0.1)}");
68+
Console.WriteLine($"Testing 222,222, a = 0.5, 10% error : {TextApproximateCount(100, 222_222, 0.5, 0.2)}");
69+
}
70+
}
71+
}

0 commit comments

Comments
 (0)