using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace VanDerCorput { /// /// Computes the Van der Corput sequence for any number base. /// The numbers in the sequence vary from zero to one, including zero but excluding one. /// The sequence possesses low discrepancy. /// Here are the first ten terms for bases 2 to 5: /// /// base 2: 0 1/2 1/4 3/4 1/8 5/8 3/8 7/8 1/16 9/16 /// base 3: 0 1/3 2/3 1/9 4/9 7/9 2/9 5/9 8/9 1/27 /// base 4: 0 1/4 1/2 3/4 1/16 5/16 9/16 13/16 1/8 3/8 /// base 5: 0 1/5 2/5 3/5 4/5 1/25 6/25 11/25 16/25 21/25 /// /// public class VanDerCorputSequence: IEnumerable> { /// /// Number base for the sequence, which must bwe two or more. /// public int Base { get; private set; } /// /// Maximum number of terms to be returned by iterator. /// public long Count { get; private set; } /// /// Construct a sequence for the given base. /// /// Number base for the sequence. /// Maximum number of items to be returned by the iterator. public VanDerCorputSequence(int iBase, long count = long.MaxValue) { if (iBase < 2) throw new ArgumentOutOfRangeException("iBase", "must be two or greater, not the given value of " + iBase); Base = iBase; Count = count; } /// /// Compute nth term in the Van der Corput sequence for the base specified in the constructor. /// /// The position in the sequence, which may be zero or any positive number. /// This number is always an integral power of the base. /// The Van der Corput sequence value expressed as a Tuple containing a numerator and a denominator. public Tuple Compute(long n) { long p = 0, q = 1; long numerator, denominator; while (n != 0) { p = p * Base + (n % Base); q *= Base; n /= Base; } numerator = p; denominator = q; while (p != 0) { n = p; p = q % p; q = n; } numerator /= q; denominator /= q; return new Tuple(numerator, denominator); } /// /// Compute nth term in the Van der Corput sequence for the given base. /// /// Base to use for the sequence. /// The position in the sequence, which may be zero or any positive number. /// The Van der Corput sequence value expressed as a Tuple containing a numerator and a denominator. public static Tuple Compute(int iBase, long n) { var seq = new VanDerCorputSequence(iBase); return seq.Compute(n); } /// /// Iterate over the Van Der Corput sequence. /// The first value in the sequence is always zero, regardless of the base. /// /// A tuple whose items are the Van der Corput value given as a numerator and denominator. public IEnumerator> GetEnumerator() { long iSequenceIndex = 0L; while (iSequenceIndex < Count) { yield return Compute(iSequenceIndex); iSequenceIndex++; } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } } class Program { static void Main(string[] args) { TestBasesTwoThroughFive(); Console.WriteLine("Type return to continue..."); Console.ReadLine(); } static void TestBasesTwoThroughFive() { foreach (var seq in Enumerable.Range(2, 5).Select(x => new VanDerCorputSequence(x, 10))) // Just the first 10 elements of the each sequence { Console.Write("base " + seq.Base + ":"); foreach(var vc in seq) Console.Write(" " + vc.Item1 + "/" + vc.Item2); Console.WriteLine(); } } } }