Normalization of a decimal value - c#

My problem is like this: I need to generate a random number from Gaussin/Norma distribution and create a histogram of a width of 0.1.
class Gaussian
{
public static double Next(Random r, double mu = 0, double sigma = 1)
{
var u1 = r.NextDouble();
var u2 = r.NextDouble();
var rand_std_normal = Math.Sqrt(-2.0 * Math.Log(u1)) *
Math.Sin(2.0 * Math.PI * u2);
var rand_normal = mu + sigma * rand_std_normal;
return rand_normal;
}
}
I am using the above function to generate a Gaussian random value.
Now, in order to create a histogram, I am in need of such a calculation that is able to automatically convert the gaussian value into an array index. Something like the following:
static void Main(string[] args)
{
const int N = 1000;
int time = N;
const double binsDistance = 0.1;
int binsCount = (int)(N * binsDistance);
Random rand = new Random();
int[] array = new int[binsCount];
int side = 0;
for (int i = 0; i < time; i++)
{
double gauss = Gaussian.Next(rand);
int binNo = Normalization.Normalize(0, binsCount - 1, gauss);
array[binNo]++;
}
}
For that, I tried two calculations.
the first one is here.
the second one is here.
The problem with the first one is, it can't handle negative numbers properly.
The problem with the second one is, it is generating too many zero values.
So, I have two questions:
What is the basic difference between #1 and #2?
How can I achieve what I am trying to do?

Related

How to split an array into intervals with given width and check count how many times, the values have appeared in each intervals C#?

In my array, arr3 has 1000 numbers in it. I have to split this array into k subintervals of width differenceofMaxMin . How can I do that? Later I have to count how many times, the values in arr3 have matched to each interval. But I am stuck at creating intervals from array with a given width.
Any kind of help will be really appreciated!
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
double[] Statistics1 = new double[500];
double[] Statistics2 = new double[500];
double Alpha1;
double Alpha2;
double RV1;
double RV2;
Random random = new Random();
public double RandomDoubleInclusive() //We are using this method because random.NextDouble() method gives random number
//between 0 and 1 where 0 is inclusive and 1 is exclusive.
//Since the value of probability lies between 0 and 1, both inclusive that's why we need
//to use this method.
{
double d = 0.0;
int i = 0;
do
{
d = random.NextDouble();
i = random.Next(2);
}
while (i == 1 && d > 0);
return d + i;
}
private void label3_Click(object sender, EventArgs e)
{
}
int i,j;
private void button1_Click(object sender, EventArgs e)
{
int SampleSize = Convert.ToInt32(textBox3.Text);
for ( i = 0; i<500;)
{
for (j = 0; j < 500;)
{
Alpha1 = RandomDoubleInclusive();
Alpha2 = RandomDoubleInclusive();
double LnPart = Math.Log(Alpha1);
double part1 = (-2) * LnPart;
double part2 = 2 * 3.14159 * Alpha2;
double CosPart = Math.Cos(part2);
double SinPart = Math.Sin(part2);
RV1 = Math.Sqrt(part1) * CosPart;
Statistics1[i] = RV1;
RV2 = Math.Sqrt(part1) * SinPart;
Statistics2[j] = RV2;
i++;
j++;
}
}
var myList = new List<double>();
myList.AddRange(Statistics1);
myList.AddRange(Statistics2);
double[] arr3 = myList.ToArray();
double Max = arr3.Max();
double Min = arr3.Min();
double differenceofMaxMin = Max - Min; //calculating size of width of interval
double k;
k = Math.Log(SampleSize,2) + 1; //calculating number of subintervals
}
}
I'm not sure I fully understand what exactly you're trying to achieve, but I can certainly try to help you out with an example on how to split an array arr3 into k subintervals with (max) number of elements differenceofMaxMin
var arr3 = Enumerable.Range(0, 1000);
// given: the max number of elements
var differenceofMaxMin = 300;
// determine the number of subintervals
// note that the last subinterval may contain less than differenceofMaxMin elements
var k = (int)Math.Ceiling((double)arr3.Count() / differenceofMaxMin);
var arr3_split = Enumerable.Range(0, k)
.Select(i => arr3.Skip(i * differenceofMaxMin).Take(differenceofMaxMin));
Looking at your method to generate a random double from [0, 1], I think it's overkill since the likelihood to actually draw exactly 1.0 is extremely low.

Random point 2D with limits

I need to generate a 1000 random numbers as [x,y] coordinates. The highest x value is 76, while for y it is 15. I have also made a Point 2D class which should read the X and Y coorinates and do some math equations (the class is called Punkt2D, and it uses X and Y like distance.X and distance.Y to calculate).
For now I only get 1000 random numbers between 0 to 75. How do I turn it into coordinate values?
(kolonner means columns, rader mens rows and nummer mens number).
public const int MaxX = 76;
public const int MaxY = 15;
public const int min = 0;
public const int rader = 1000;
public const int kolonner = 2;
public static void Main(string[] args)
{
Random r = new Random();
int[,] nummer = new int[kolonner,rader];
for (int m = 0; m < kolonner; m++)
{
for (int n = 0; n < 1000; n++)
{
nummer[m,n] = r.Next(0,MaxX);
Console.WriteLine(Convert.ToString(nummer[m, n]));
}
}
}
I did also start on this method here, where I removed the loops.
int row = r.Next(nummer.GetLength(0));
int column = r.Next(nummer.GetLength(1));
int randomNummer = nummer[row, column];
Console.WriteLine(Convert.ToString(nummer));
Thanks in advance.
I see two ways to generate random points. Let's assume ranges of x = {0..M-1} and y = {0..N-1}
Create two separate random numbers int x = random.Next(M); int y = random.Next(N). The lower bound is 0. Note that the upper bound is exclusive. Therefore M and N must be 1 higher than the maximum values. They represent the number of possible values along one axis (the number of pixels in an image).
const int M = 77, Y = 16; // Gives range of { 0..76, 0..15 }.
Generate one random value int r = random.Next(M * N); and then get the coordinates with int x = r % M; int y = r / M; (% is the modulo operator yielding the remainder of the division).
You can get a point with:
var p = new Point(x, y);

Riemann Midpoint Sum getting crazy numbers

I'm working on a Midpoint Riemann Sum program, and it finds the integral of a randomly generated function called f.
Here's what wrote:
public static double FindIntegral (double start, double end, function f)
{
double sum = 0;
double stepsize = 1E-2;
int numSteps = (int)((end - start) / stepsize);
for (int i = 0; i < numSteps; i++)
{
sum += f(start + (stepsize * (i + 0.5)));
}
return sum * stepsize;
}
The function returns numbers that are too low (I have a reliable checking mechanism).
I put in x^3 for f, and I got the right answer. I tried a couple of more integrable functions and got a good answer. But somehow once I put in f it doesn't work.
I got the math formula for "Riemann Midpoint Sum" from here.
My implementation below seems to get the right answer (using the example function on the page). I used a class because 1) I could make the algorithm work specifying either the step size or the number of rectangles (I preferred the latter) and 2) I didn't see any reason to hard-code either into the algorithm.
As it turns out your code seemed to work just fine (see below); Make sure the code you have here in your question is what you're executing and make sure your expected result is accurate and that you're supplying good inputs (i.e. you don't have start and end backwards or the wrong function f or something). In other words what you provided in your question looks fine. Note double is approximate in C# (floating point arithmetic, in general) so to compare equality you can't use == unless you want exact if you're using unit tests or something.
public class Program
{
public static void Main()
{
function f = x => 50 / (10 + x * x);
// 9.41404285216233
Console.Out.WriteLine(new RiemannMidpointSum(6).FindIntegral(1, 4, f));
// 9.41654853716462
Console.Out.WriteLine(new RiemannMidpointSum(1E-2).FindIntegral(1, 4, f));
// 9.41654853716462
Console.Out.WriteLine(Program.FindIntegral(1, 4, f));
}
// This is your function.
public static double FindIntegral (double start, double end, function f)
{
double sum = 0;
double stepsize = 1E-2;
int numSteps = (int)((end - start) / stepsize);
for (int i = 0; i < numSteps; i++)
{
sum += f(start + (stepsize * (i + 0.5)));
}
return sum * stepsize;
}
}
public delegate double function(double d);
public class RiemannMidpointSum
{
private int? _numberOfRectangles;
private double? _widthPerRectangle;
public RiemannMidpointSum(int numberOfRectangles)
{
// TODO: Handle non-positive input.
this._numberOfRectangles = numberOfRectangles;
}
public RiemannMidpointSum(double widthPerRectangle)
{
// TODO: Handle non-positive input.
this._widthPerRectangle = widthPerRectangle;
}
public double FindIntegral(double a, double b, function f)
{
var totalWidth = b - a;
var widthPerRectangle = this._widthPerRectangle ?? (totalWidth / this._numberOfRectangles.Value);
var numberOfRectangles = this._numberOfRectangles ?? ((int)Math.Round(totalWidth / this._widthPerRectangle.Value, 0));
double sum = 0;
foreach (var i in Enumerable.Range(0, numberOfRectangles))
{
var rectangleMidpointX = a + widthPerRectangle * i + widthPerRectangle / 2;
var rectangleHeightY = f(rectangleMidpointX);
var rectangleArea = widthPerRectangle * rectangleHeightY;
sum += rectangleArea;
}
return sum;
}
}

How to do smooth Random in C# with step?

How to generate random value from 5 to 10 with step 0.4?
I tried:
var numberOfSteps = 0.4;
var _step = (maximum - minimum) / numberOfSteps;
var difference = maximum - minimum;
var stepsToDifference = Math.Round(difference / _step);
return Convert.ToString(minimum + _step * stepsToDifference);
Do you mean you want the number to be 5, 5.4, 5.8, ... 10? As 5 and 10 are 5 apart and not evenly divisible by .4, you will have to either stop at 9.8 or at 10.2 or stop at 10 with a short step at the last.
But here is how you can get a random number that is a member of that set (will be any number from 5 to 9.8 on the even .4 step).
Random rand = new Random();
float randomInSet = ((float)rand.Next(0,12)*.4)+5;
Please let me know if this is not what you had in mind.
How about something like this:
Random rand = new Random();
int intPart = 0;
int multiplesOfPointFour = 0;
bool doAgain = true;
double finalValue = 0.0;
while (doAgain)
{
intPart = rand.Next(5, 8);
multiplesOfPointFour = rand.Next(0, 6);
finalValue = intPart + (multiplesOfPointFour * 0.4);
Console.WriteLine("Value is: " + finalValue.ToString());
Console.Write("Press any key to go again...");
Console.ReadKey();
}
So we pick an integer between 5 and 10 and then add 0.4 a random number of times between 0 and 12 to that integer, because 5.0 / 0.4 = 12.5
Was trying to generate a random Hue to create really different colors, so here it is:
//***************************************************************************
public static partial class RndExtensions
//***************************************************************************
{
//-------------------------------------------------------------
public static double NextDouble(this Random rnd, double from, double to, double step)
//-------------------------------------------------------------
{
var delta = to - from;
var nbOfSteps = (int)(delta / step);
var randomStep = rnd.Next(0, nbOfSteps);
return step*randomStep + from;
}
//-------------------------------------------------------------
public static double Next(this Random rnd, int from, int to, int step)
//-------------------------------------------------------------
{
var delta = to - from;
var nbOfSteps = (int)(delta / step);
var randomStep = rnd.Next(0, nbOfSteps);
return step * randomStep + from;
}
}
Used as
Random rnd = new Random();
var randomHue = rnd.NextDouble(0, 359, 25);

Array data normalization

I have an array of values (between -1.0 and 1.0) that represent intensity (Black to White). I need a way to map the double values from -1.0 through 1.0 to 0 through 255 and back.
More generalized, I have an array of data and I need to map from the min and max value of the data to a supplied min and max. Basic structure should be like:
private static int[] NormalizeData(double[] data, int min, int max)
{
var sorted = data.OrderBy(d => d);
double dataMax = sorted.First();
double dataMin = sorted.Last();
int[] ret = new int[data.Length];
for (int i = 0; i < data.Length; i++)
{
ret[i] = (int)data[i]; // Normalization here
}
return ret;
}
This works:
private static int[] NormalizeData(IEnumerable<double> data, int min, int max)
{
double dataMax = data.Max();
double dataMin = data.Min();
double range = dataMax - dataMin;
return data
.Select(d => (d - dataMin) / range)
.Select(n => (int)((1 - n) * min + n * max))
.ToArray();
}
The first select normalizes the input to be from 0 to 1 (0 being minimum, 1 being the maximum). The second select takes that normalized number, and maps it to the new minimum and maximum.
Note that using the LINQ Min() and Max() functions are faster than sorting the input for larger datasets: O(n) vs. O(n * lg(n)).
Also, if you want to go the other way, then you'll want it to return doubles instead of ints.
public static double Scale(this double elementToScale,
double rangeMin, double rangeMax,
double scaledRangeMin, double scaledRangeMax)
{
var scaled = scaledRangeMin + ((elementToScale - rangeMin) * (scaledRangeMax - scaledRangeMin) / (rangeMax - rangeMin));
return scaled;
}
Usage:
// double [-1,1] to int [0-255]
int[] integers = doubles.Select(x => x.Scale(-1,1,0,255)).ToArray();
// int [0-255] to double [-1,1]
double[] doubles = integers.Select(x => ((double)x).Scale(0,255,-1,1)).ToArray();
If you don't know the min and max in advance ([0-255] and [-1,1] in the example), you can use LINQ Min() and Max()
private static int[] NormalizeData(double[] data, int min, int max) {
int[] ret = new int[data.Length];
for (int i = 0; i < data.Length; i++) {
ret[i] = (int)((max * (data[i] + 1)) / 2);
}
return ret;
}
static void Main(string[] args) {
double[] data = { 1.0, -1, 0, -.5, .5 };
int[] normalized = NormalizeData(data, 0, 255);
foreach (var v in normalized) {
Console.WriteLine(v);
}
}
EDIT:
How about this:
private static int[] NormalizeData(double[] data, int min, int max)
{
var sorted = data.OrderBy(d => d);
double dataMax = sorted.First();
double dataMin = sorted.Last();
int[] ret = new int[data.Length];
double avgIn = (double)((min + max) / 2.0);
double avgOut = (dataMax + dataMin) / 2.0);
for (int i = 0; i < data.Length; i++)
{
ret[i] = (int) Math.Round(avgOut * (data[i] + avgIn) / 2);
}
return ret;
}
Assuming a strictly linear transformation and that you want dataMin to map to min and dataMax to map to max:
double dataRange = dataMax - dataMin;
int newRange = max - min;
double pct = (data[i] - dataMin) / dataRange;
int newValue = Math.Round(min + (pct * newRange));
That can certainly be optimized, but it shows the basic idea. Basically, you figure out the position (as a percentage) of the value in the original range and then map that percentage to the target range.
Note that if dataMin is -0.5 and dataMax is 0.5, this might not produce the results that you're looking for because -0.5 will map to 0 and 0.5 will map to 255. If you want things to map exactly as stated, you'll have to define the source range as well.
As an aside, there's no particular reason to sort the items just to get the min and max. You can write:
double dataMax = data.Max();
double dataMin = data.Min();
To be able to normalize your array which in this example acts a vector mathematically you need to define what length the vector is in (how many dimensions).
It's not really clear from the example if you want to normalize the entire array taking all elements in the array into account. If so then you calculate the dot product of the array, store the dot products square root as the length of the array. then you divide every term with that length to normalize the array to a length of 1.0.
In the case above you did not actually describe a normalization of the data but a conversion. To solve that you could use something like the following:
private static double[] convertToScale(double[] data, double oldMin, double oldMax,double min, double max)
{
double oldDiff = 0 - oldMin;
double oldScale = oldMax - oldMin;
double diff = 0 - min;
double scale = max - min;
int[] ret = new double[data.Length];
for (int i = 0; i < data.Length; i++)
{
double scaledFromZeroToOne = (oldDiff+data[i])/oldScale; // Normalization here [0,1]
double value = (scaledFromZeroToOne*scale)-diff;
ret[i] = value;
}
return ret;
}
This function i believe would solve the problem described above.
You can call it like following row:
double[] result = convertToScale(input,-1.0,1.0,0,255);
And then cast everything to int if you'd rather have the values represented as ints.
Hope it helps.

Categories

Resources