How to calculate Simple Moving Average in C#? - c#

I'm just lost and can't seem to know what to do to calculate the simple moving average?
This is one of the method in the file which is used to calculate the simple moving average.
public async Task<decimal?> UpdateAsync(decimal? value, CancellationToken cancelToken)
{
await Task.Run(() =>
{
var av = default(decimal?);
if (_av.Count - 1 >= _p)
{
}
else
{
av = value;
}
_av.Add(av);
return av;
}, cancelToken).ConfigureAwait(false);
throw new Exception("major issue");
}
}

Let's start with the question:
I'm just lost and can't seem to know what to do to calculate the
simple moving average?
Given
public static class Extensions
{
public static IEnumerable<decimal> MovingAvg(this IEnumerable<decimal> source, int period)
{
var buffer = new Queue<decimal>();
foreach (var value in source)
{
buffer.Enqueue(value);
// sume the buffer for the average at any given time
yield return buffer.Sum() / buffer.Count;
// Dequeue when needed
if (buffer.Count == period)
buffer.Dequeue();
}
}
}
Usage
static void Main(string[] args)
{
var input = new decimal[] { 1, 2, 2, 4, 5, 6, 6, 6, 9, 10, 11, 12, 13, 14, 15 };
var result = input.MovingAvg(2);
Console.WriteLine(string.Join(", ",result));
}
Output
1, 1.5, 2, 3, 4.5, 5.5, 6, 6, 7.5, 9.5, 10.5, 11.5, 12.5, 13.5, 14.5

So first of all what is moving average
A simple moving average is a method for computing an average of a stream of numbers by only averaging the last P numbers from the stream, where P is known as the period.
Next is the code as how I imagined my moving average to be implemented. It is possible to use LINQ but at each and every step after we add a number I want my Average to be updated.
My code is heavily commented so please read the comments.
public class MovingAverageCalculator {
/// <summary>
/// Maximum number of numbers this moving average calculator can hold.
/// </summary>
private readonly int maxElementCount;
/// <summary>
/// Numbers which will be used for calculating moving average.
/// </summary>
private readonly int[] currentElements;
/// <summary>
/// At which index the next number will be added.
/// </summary>
private int currentIndex;
/// <summary>
/// How many elements are there currently in this moving average calculator.
/// </summary>
private int currentElementCount;
/// <summary>
/// Current total of all the numbers that are being managed by this moving average calculator
/// </summary>
private double currentTotal;
/// <summary>
/// Current Average of all the numbers.
/// </summary>
private double currentAvg;
/// <summary>
/// An object which can calcauclate moving average of given numbers.
/// </summary>
/// <param name="period">Maximum number elements</param>
public MovingAverageCalculator(int period) {
maxElementCount = period;
currentElements = new int[maxElementCount];
currentIndex = 0;
currentTotal = 0;
currentAvg = 0;
}
/// <summary>
/// Adds an item to the moving average series then updates the average.
/// </summary>
/// <param name="number">Number to add.</param>
public void AddElement(int number){
// You can only have at most maximum elements in your moving average series.
currentElementCount = Math.Min(++currentElementCount, maxElementCount);
// IF your current index reached the maximum allowable number then you must reset
if (currentIndex == maxElementCount){
currentIndex = 0;
}
// Copy the current index number to the local variable
var temp = currentElements[currentIndex];
// Substract the value from the current total because it will be replaced by the added number.
currentTotal -= temp;
// Add the number to the current index
currentElements[currentIndex] = number;
// Increase the total by the added number.
currentTotal += number;
// Increase index
currentIndex++;
// Calculate average
currentAvg = (double)currentTotal / currentElementCount;
}
/// <summary>
/// Gets the current average
/// </summary>
/// <returns>Average</returns>
public double GetAverage() => currentAvg;
}
And lastly, I checked your code but It does not make sense to me

Related

C# how to save values from a array to a new array while not knowing the length of the new array

so for example, this code here does the job fine for this specific task, but I really don't like how I need to reuse the loop 2 times to get the size and then implement the method, it feels not right.
public static int[] FilterByDigit(int[] source, int digit)
{
int size = 0;
for (int i = 0; i < source.Length; i++)
{
bool result = source[i].ToString().Contains(digit.ToString());
if (result)
{
size++;
}
}
int[] arr = new int[size];
int count = 0;
for (int i = 0; i < source.Length; i++)
{
bool result = source[i].ToString().Contains(digit.ToString());
if (result)
{
arr[count] = source[i];
count++;
}
}
return arr;
}
Is there anyway to get the size in the first loop and then implement the method, having no need of the second loop?
If you need to understand this particular task:
/// <summary>
/// Returns new array of elements that contain expected digit from source array.
/// </summary>
/// <param name="source">Source array.</param>
/// <param name="digit">Expected digit.</param>
/// <returns>Array of elements that contain expected digit.</returns>
/// <exception cref="ArgumentNullException">Thrown when array is null.</exception>
/// <exception cref="ArgumentException">Thrown when array is empty.</exception>
/// <exception cref="ArgumentOutOfRangeException">Thrown when digit value is out of range (0..9).</exception>
/// <example>
/// {1, 2, 3, 4, 5, 6, 7, 68, 69, 70, 15, 17} => { 7, 70, 17 } for digit = 7.
/// </example>
try this
public static int[] FilterByDigit(int[] source, int digit)
{
return source.Where(s => s.ToString().Contains(digit.ToString()));
}
output
int digit=7;
var source = new int[] {1, 2, 3, 4, 5, 6, 7, 68, 69, 70, 15, 17};
var result =FilterByDigit(source,digit);
var output=string.Join(",",result);
7,70,17

How do I calculate bpm (beats per minute)?

I'm trying to write a Winforms application that calculates the beats per minute of click, similar to this website: https://www.all8.com/tools/bpm.htm but nothing works for me.
I've tried to create a System.Diagnostics.Stopwatch object to count the number of milliseconds, and divide that by 60,000 to get the number of minutes that pass, but that doesn't count what the future
public Stopwatch stopwatch = new Stopwatch();
public Form1()
{
InitializeComponent();
}
float i = 0f;
private void Button1_Click(object sender, EventArgs e)
{
if (!stopwatch.IsRunning) { stopwatch.Start(); }
i++;
speed.Text = String.Format("Speed: {0} bpm\nClicks: {1} Clicks", i / Millis(), i);
}
private float Millis()
{
var returntype = stopwatch.ElapsedMilliseconds / 60000;
return returntype + 1;
}
This just counts the number of times you've clicked the button and divides it by the number of minutes that have passed, and doesn't predict at the rate of clicking.
This is very similar to some code I wrote to calculate FPS of an encoding process that I wrote some time ago.
Start with this code and then adapt it to your needs. The Calculate method will take a bool indicating whether it's a click or not. You'll call it with True on every click, and have a timer call it with False every second. Then you simply bind the BMP to the property of this class for display.
This should be enough to get you started. I recommend keeping the logic of that calculation in a specialized class to not clutter the main class.
/// <summary>
/// Allows calculating the time left during an encoding process.
/// </summary>
public class TimeLeftCalculator {
private KeyValuePair<DateTime, long>[] progressHistory;
private int iterator;
private bool fullCycle;
private long lastPos;
private long frameCount;
private int historyLength;
/// <summary>
/// After calling Calculate, returns the estimated processing time left.
/// </summary>
public TimeSpan ResultTimeLeft { get; private set; }
/// <summary>
/// After calling Calculate, returns the estimated processing rate per second.
/// </summary>
public double ResultFps { get; private set; }
protected readonly IEnvironmentService environment;
/// <summary>
/// Initializes a new instance of the TimeLeftCalculator class.
/// </summary>
/// <param name="frameCount">The total number of frames to encode.</param>
/// <param name="historyLength">The number of status entries to store. The larger the number, the slower the time left will change. Default is 20.</param>
public TimeLeftCalculator(long frameCount, int historyLength = 20) : this(new EnvironmentService(), frameCount, 20) { }
/// <summary>
/// Initializes a new instance of the TimeLeftCalculator class.
/// </summary>
/// <param name="environmentService">A reference to an IEnvironmentService.</param>
/// <param name="frameCount">The total number of frames to encode.</param>
/// <param name="historyLength">The number of status entries to store. The larger the number, the slower the time left will change. Default is 20.</param>
public TimeLeftCalculator(IEnvironmentService environmentService, long frameCount, int historyLength = 20) {
this.environment = environmentService ?? throw new ArgumentNullException(nameof(environmentService));
this.FrameCount = frameCount;
this.HistoryLength = historyLength;
progressHistory = new KeyValuePair<DateTime, long>[historyLength];
}
/// <summary>
/// Gets or sets the total number of frames to encode.
/// </summary>
public long FrameCount {
get => frameCount;
set => frameCount = value >= 0 ? value : throw new ArgumentOutOfRangeException(nameof(FrameCount));
}
/// <summary>
/// Gets or sets the number of status entries to store. The larger the number, the slower the time left will change.
/// </summary>
public int HistoryLength {
get => historyLength;
set => historyLength = value >= 1 ? value : throw new ArgumentOutOfRangeException(nameof(HistoryLength));
}
/// <summary>
/// Calculates the time left and fps. Result will be in ResultTimeLeft and ResultFps.
/// </summary>
/// <param name="pos">The current frame position.</param>
public void Calculate(long pos) {
if (pos < 0)
return;
TimeSpan Result = TimeSpan.Zero;
progressHistory[iterator] = new KeyValuePair<DateTime, long>(environment.Now, pos);
lastPos = pos;
// Calculate SampleWorkTime and SampleWorkFrame for each host
TimeSpan SampleWorkTime = TimeSpan.Zero;
long SampleWorkFrame = 0;
int PosFirst = -1;
if (fullCycle) {
PosFirst = (iterator + 1) % HistoryLength;
} else if (iterator > 0)
PosFirst = 0;
if (PosFirst > -1) {
SampleWorkTime += progressHistory[iterator].Key - progressHistory[PosFirst].Key;
SampleWorkFrame += progressHistory[iterator].Value - progressHistory[PosFirst].Value;
}
if (SampleWorkTime.TotalSeconds > 0 && SampleWorkFrame >= 0) {
ResultFps = SampleWorkFrame / SampleWorkTime.TotalSeconds;
long WorkLeft = FrameCount - pos;
if (WorkLeft <= 0)
ResultTimeLeft = TimeSpan.Zero;
else if (ResultFps > 0)
ResultTimeLeft = TimeSpan.FromSeconds(WorkLeft / ResultFps);
}
iterator = (iterator + 1) % HistoryLength;
if (iterator == 0)
fullCycle = true;
}
}
Here's a couple of utility ex. methods that convert between BPM and TimeSpan:
public static class BpmExtensions
{
const long SecondsPerMinute = TimeSpan.TicksPerMinute / TimeSpan.TicksPerSecond;
public static int ToBpm(this TimeSpan timeSpan)
{
var seconds = 1 / timeSpan.TotalSeconds;
return (int)Math.Round(seconds * SecondsPerMinute);
}
public static TimeSpan ToInterval(this int bpm)
{
var bps = (double)bpm / SecondsPerMinute;
var interval = 1 / bps;
return TimeSpan.FromSeconds(interval);
}
}

How to check if number is a Mersenne prime?

What is an efficient way to check if a Int32 n is a Mersenne prime?
This is my attempt :
Apparently this code returns true for some numbers which are a Mersenne prime e.g. 31 but it doesn't for others such as 127.
Can somebody tell me whats wrong with my code?
/// <summary>
/// Checks if a nubmer is a mersenne prime
/// </summary>
/// <param name="candidate"></param>
/// <returns></returns>
public static bool IsMersennePrime(uint n)
{
var x = Math.Pow(2, n) - 1;
return IsPrime((uint)x);
}
/// <summary>
/// Checks if a nubmer is a prime
/// </summary>
/// <param name="candidate"></param>
/// <returns>true if number is a prime false if its not a prime</returns>
private static bool IsPrime(uint candidate)
{
//
// Test whether the parameter is a prime number.
//
if ((candidate & 1) == 0)
{
if (candidate == 2)
{
return true;
}
else
{
return false;
}
}
int num = (int)Math.Sqrt((double)candidate);
for (int i = 3; i <= num; i += 2)
{
if ((candidate % i) == 0)
{
return false;
}
}
return true;
}
Since you just want Mersenne primes which fits into an uint the best way is to check against actual values. Read more about A000043 and A000668.
private static int[] A000043 = new int[] { 2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689, 9941, 11213, 19937, 21701, 23209, 44497, 86243, 110503, 132049, 216091, 756839, 859433, 1257787, 1398269, 2976221, 3021377, 6972593, 13466917, 20996011, 24036583, 25964951, 30402457, 32582657 };
private static int[] A000668 = new int[] { 3, 7, 31, 127, 8191, 131071, 524287, 2147483647 };
public static bool IsInA000668(int value) => A000668.Contains(value);
public static bool IsInA000043(int value) => A000043.Contains(value);

How to round a integer to the close hundred?

I don't know it my nomenclature is correct! Anyway, these are the integer I have, for example :
76
121
9660
And I'd like to round them to the close hundred, such as they must become :
100
100
9700
How can I do it faster in C#? I think about an algorithm, but maybe there are some utilities on C#?
Try the Math.Round method. Here's how:
Math.Round(76d / 100d, 0) * 100;
Math.Round(121d / 100d, 0) * 100;
Math.Round(9660d / 100d, 0) * 100;
I wrote a simple extension method to generalize this kind of rounding a while ago:
public static class MathExtensions
{
public static int Round(this int i, int nearest)
{
if (nearest <= 0 || nearest % 10 != 0)
throw new ArgumentOutOfRangeException("nearest", "Must round to a positive multiple of 10");
return (i + 5 * nearest / 10) / nearest * nearest;
}
}
It leverages integer division to find the closest rounding.
Example use:
int example = 152;
Console.WriteLine(example.Round(100)); // round to the nearest 100
Console.WriteLine(example.Round(10)); // round to the nearest 10
And in your example:
Console.WriteLine(76.Round(100)); // 100
Console.WriteLine(121.Round(100)); // 100
Console.WriteLine(9660.Round(100)); // 9700
Try this expression:
(n + 50) / 100 * 100
Caveat: only works for non-negative n.
Just some addition to #krizzzn's accepted answer...
Do note that the following will return 0:
Math.Round(50d / 100d, 0) * 100;
Consider using the following and make it return 100 instead:
Math.Round(50d / 100d, 0, MidpointRounding.AwayFromZero) * 100;
Depending on what you're doing, using decimals might be a better choice (note the m):
Math.Round(50m / 100m, 0, MidpointRounding.AwayFromZero) * 100m;
I know this is an old thread. I wrote a new method. Hope this will be useful for some one.
public static double Round(this float value, int precision)
{
if (precision < -4 && precision > 15)
throw new ArgumentOutOfRangeException("precision", "Must be and integer between -4 and 15");
if (precision >= 0) return Math.Round(value, precision);
else
{
precision = (int)Math.Pow(10, Math.Abs(precision));
value = value + (5 * precision / 10);
return Math.Round(value - (value % precision), 0);
}
}
Example:
float value = 6666.677777F;
Console.Write(value.Round(2)); //6666.68
Console.Write(value.Round(0)); //6667
Console.Write(value.Round(-2)); //6700
Hi i write this extension this gets the next hundred for each number you pass
/// <summary>
/// this extension gets the next hunfìdred for any number you whant
/// </summary>
/// <param name="i">numeber to rounded</param>
/// <returns>the next hundred number</returns>
/// <remarks>
/// eg.:
/// i = 21 gets 100
/// i = 121 gets 200
/// i = 200 gets 300
/// i = 1211 gets 1300
/// i = -108 gets -200
/// </remarks>
public static int RoundToNextHundred(this int i)
{
return i += (100 * Math.Sign(i) - i % 100);
//use this line below if you want RoundHundred not NEXT
//return i % 100 == byte.MinValue? i : i += (100 * Math.Sign(i) - i % 100);
}
//and for answer at title point use this algoritm
var closeHundred = Math.Round(number / 100D)*100;
//and here the extension method if you prefer
/// <summary>
/// this extension gets the close hundred for any number you whant
/// </summary>
/// <param name="number">number to be rounded</param>
/// <returns>the close hundred number</returns>
/// <remarks>
/// eg.:
/// number = 21 gets 0
/// number = 149 gets 100
/// number = 151 gets 200
/// number = -149 gets -100
/// number = -151 gets -200
/// </remarks>
public static int RoundCloseHundred(this int number)
{
return (int)Math.Round(number / 100D) * 100;
}
If you only want to round integer numbers up (as the OP actually did), then you can resort to this solution:
public static class MathExtensions
{
public static int RoundUpTo(this int number, int nearest)
{
if (nearest < 10 || nearest % 10 != 0)
throw new ArgumentOutOfRangeException(nameof(nearest), $"{nameof(nearest)} must be a positive multiple of 10, but you specified {nearest}.");
int modulo = number % nearest;
return modulo == 0 ? number : modulo > 0 ? number + (nearest - modulo) : number - modulo;
}
}
If you want to perform floating-point (or decimal) rounding, then resort to the answers of #krizzzn and #Jim Aho.
int num = 9660;
int remainder = num % 100;
Console.WriteLine(remainder < 50 ? num - remainder : num + (100 -remainder));
Note: I haven't tested this thoroughly.
I had a similar project internally where the business requirements were to search within the 100's range of a given number and find duplicate DB records. So if the user was using line 856 I would search 800 - 899. If the user was using 8567 I would search 8500 - 8599. Not an exact rounding by 100's, but thought I would include my unique approach as some of these basic coding questions are embedded within a larger business project. To test this I seeded a decimal list from 1 - 99999 and spit the results out into a file.
/// <summary>
/// This method accepts an inbound Line Number and returns the line range
/// in the form of lowest to highest based on 100's
/// Example would be 9122 returns 9100 - 9199
/// It's used for generating some additional BOM Temp functionality.
/// </summary>
/// <param name="inboundNumber"></param>
/// <returns></returns>
public static ProjectLineRange CalculateLineRange(decimal inboundNumber)
{
var lineRange = new ProjectLineRange();
var numberLength = inboundNumber.ToString(CultureInfo.InvariantCulture).Length;
switch (numberLength)
{
case 0: //NULL?
break;
case 1: //Represents 1 - 9
lineRange.LineBottom = 1;
lineRange.LineTop = 99;
break;
case 2: //Represents 10 - 99
lineRange.LineBottom = 1;
lineRange.LineTop = 99;
break;
case 3: //Represents 100 - 999
lineRange = CalculateHundredsRange((int)(inboundNumber / 100));
break;
case 4: //Represents 1000 - 9999
lineRange = CalculateThousandsRange(
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(1, 1)),
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(0, 1)));
break;
case 5: //Represents 10000 - 99999
lineRange = CalculateTenThousandsRange(
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(2, 1)),
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(1, 1)),
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(0, 1)));
break;
}
return lineRange;
}
public class ProjectLineRange
{
public decimal LineBottom { get; set; }
public decimal LineTop { get; set; }
}
/// <summary>
/// Helper method to return the range for the 100's place
/// </summary>
/// <param name="hundredsPlaceValue"></param>
/// <returns></returns>
public static ProjectLineRange CalculateHundredsRange(int hundredsPlaceValue)
{
var tempLineRange = new ProjectLineRange();
tempLineRange.LineBottom = hundredsPlaceValue * 100;
tempLineRange.LineTop = tempLineRange.LineBottom + 99;
return tempLineRange;
}
/// <summary>
/// Helper method to return the range for the 100's place when factoring a 1000's number
/// </summary>
/// <param name="hundredsPlaceValue"></param>
/// <param name="thousandsPlaceValue"></param>
/// <returns></returns>
public static ProjectLineRange CalculateThousandsRange(int hundredsPlaceValue, int thousandsPlaceValue)
{
var tempLineRange = new ProjectLineRange();
var tempThousands = thousandsPlaceValue * 1000;
var hundredsRange = CalculateHundredsRange(hundredsPlaceValue);
tempLineRange.LineBottom = tempThousands + hundredsRange.LineBottom;
tempLineRange.LineTop = tempThousands + hundredsRange.LineTop;
return tempLineRange;
}
/// <summary>
/// Helper method to return the range for the 100's place when factoring a 10000's number
/// </summary>
/// <param name="hundredsPlaceValue"></param>
/// <param name="thousandsPlaceValue"></param>
/// <param name="tenThousandsPlaceValue"></param>
/// <returns></returns>
public static ProjectLineRange CalculateTenThousandsRange(int hundredsPlaceValue, int thousandsPlaceValue, int tenThousandsPlaceValue)
{
var tempLineRange = new ProjectLineRange();
var tempThousands = thousandsPlaceValue * 1000;
var tempTenThousands = tenThousandsPlaceValue * 10000;
var hundredsRange = CalculateHundredsRange(hundredsPlaceValue);
tempLineRange.LineBottom = tempTenThousands + tempThousands + hundredsRange.LineBottom;
tempLineRange.LineTop = tempTenThousands + tempThousands + hundredsRange.LineTop;
return tempLineRange;
}
public static class Maths
{
public static int Round(this int value, int precision)
{
var coef = Math.Pow(10, Math.Abs(precision));
var x = (int)Math.Round(value / coef, 0);
return x * (int)coef;
}
}
var number = 34569;
Debug.WriteLine(number.Round(0));//34569
Debug.WriteLine(number.Round(1));//34570
Debug.WriteLine(number.Round(2));//34600
Debug.WriteLine(number.Round(3));//35000
Debug.WriteLine(number.Round(4));//30000
Debug.WriteLine(number.Round(5));// 0
Debug.WriteLine(number.Round(6));// 0

How to write a Linear Congruential Generator (LCG) in C#? Or are there any well known implementations?

I am wanting to generate a random array of sequences that repeat and only use each number once. For example, given a range of 0-9 with 2 different seeds you might get
Seed 1: 7 3 5 9 0 8 1 2 6 4 | 7 3 5 9 0 8 1 2 6 4 | 7 3 5 9 0 8 1 2 6 4
Seed 2: 2 5 7 1 4 9 6 8 3 0 | 2 5 7 1 4 9 6 8 3 0 | 2 5 7 1 4 9 6 8 3 0
From what I understand, a Linear Congruential Random Number Generator or LCRNG or LCG can give me this http://en.wikipedia.org/wiki/Linear_congruential_generator
Any idea if an implementation exists in C# or how I would get started with writing one.
How does a Mersenne Twister differ from an LCG?
Not sure all of my questions are answered, but here is what I ended up using. Because I am bounding the sample size to the range of values from max to min, I am selecting a different prime number that stays static as long as the same initial seed is given. I do this because I want the same sequence given the same seed and the same min/max bounds for repeatability of testing.
Please critique anything I do here, this is just what I came up with in a jiffy:
using System;
using System.Collections.Generic;
namespace FULLCYCLE
{
public class RandomNumber
{
private int _value;
private int _prime;
private static List<int> primes = new List<int>()
{
11,
23,
47,
97,
797,
1597,
6421,
25717,
51437,
102877,
411527,
823117,
1646237,
3292489,
6584983,
13169977,
26339969,
52679969,
105359939,
210719881,
421439783,
842879579,
1685759167
};
public RandomNumber( int seed )
{
_prime = primes[seed%primes.Count];
_value = seed;
}
public int Next( int min, int max )
{
int maxrate = (max-min+1);
if (_value > maxrate)
{
_value = _value % maxrate;
}
_value = (_value + _prime) % maxrate;
return _value + min;
}
}
}
Why not just use the existing Random class and a Knuth shuffle on your input sequence?
Regarding your edit, there are several problems with your LCG as a random number generator...
It can produce obvious patterns:
// generates 3, 4, 5, 6, 7, 8, 9, 0, 1, 2
var rng = new RandomNumber(42);
for (int i = 0; i < 10; i++) Console.WriteLine(rng.Next(0, 9));
It can repeat itself:
// generates 579, 579, 579, 579, 579, 579, 579, 579, 579, 579
var rng = new RandomNumber(123);
for (int i = 0; i < 10; i++) Console.WriteLine(rng.Next(456, 51892));
There are many other seed/min/max combinations that will generate problematic results.
Try the following code:
namespace System
{
/// <summary>
/// Represents a pseudo-random number generator using the linear congruential method:
/// X[i+1] = (a • X[i] + c) % m (where i is greater than or equal to 0).
/// </summary>
public class LinearCongruentialRandom : Random
{
private int _x = 1971111612;
private int _a = 2147483629;
private int _c = 2147483587;
private int _m = 2147483647;
/// <summary>
/// Initializes a new instance of <see cref="LinearCongruentialRandom"/> with default values.
/// </summary>
public LinearCongruentialRandom()
{
= base.Next(0, _m);
}
/// <summary>
/// Initializes a new instance of <see cref="LinearCongruentialRandom"/> with default values.
/// </summary>
public LinearCongruentialRandom(int seed)
{
if (seed >= _m) throw new ArgumentOutOfRangeException(nameof(seed), seed, null);
_x = seed;
}
/// <summary>
/// Initializes a new instance of <see cref="LinearCongruentialRandom"/> with the specified parameters.
/// </summary>
/// <param name="seed">Initial seed value less than m.</param>
/// <param name="a">A multiple of p for every prime p that is a divisor of m.</param>
/// <param name="c">Increment c. The numbers c and m must be relatively prime.</param>
/// <param name="m">The length of the repetition period m. The numbers c and m must be relatively prime.</param>
public LinearCongruentialRandom(int seed, int a, int c, int m) : this(seed)
{
_a = a;
_c=c;
_m=m;
}
/// <inheritdoc cref="Random.Next()"/>
public override int Next()
{
return _x = (_a * _x + _c) % _m;
}
/// <inheritdoc cref="Random.NextBytes(byte[])"/>
public override void NextBytes(byte[] buffer)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer));
unchecked
{
for (int index = 0; index < buffer.Length; ++index)
buffer[index] = (byte)Next();
}
}
}
}

Categories