I was reading this article and I trying to follow their code example but I think I am missing a library.
They have this :
First, let's create a 2D matrix with some random data. We'll use the
System.Random class to generate pseudo-random numbers:
var rand = new Random();
var matrix = new double[5, 5];
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
matrix = rand.NextDouble() * 100;
}
}
Now that we have our data, we can calculate the mean and standard deviation:
double mean = matrix.Average();
double stdDev = Math.Sqrt(matrix.Variance());
but when I tried that in C# does, I get this compile time error:
Severity Code Description Project File Line Suppression State
Error CS1061 'double[,]' does not contain a definition for 'Variance' and no
accessible extension method 'Variance' accepting a first argument of type 'double[,]'
could be found (are you missing a using directive or an assembly reference?)
I tried adding
using System.Numerics;
but it did not help
In case you want to apply Linq method to 2D array T[,] items, you can use OfType() (or Cast<T>()) to obtain a enumeration IEnumeration<T>.
For instance, in your case with Average() you can put it as
using System.Linq;
...
var matrix = new double[5,5];
...
double mean = matrix
.OfType<double>()
.Average();
Since standard Linq doesn't have (at least in .Net 6) Variance method, we should do a simple statistics. Having a sequence of x = {x_1, x_2, x_3, ..., x_N} of N items the variance will be
Var(x) = Sum(x * x) / N - Sum(x) * Sum(x) / N / N
In our case it can be a simple Aggregate:
// Let's compute all required statistics
// n - number of items
// s - sum of items
// s - sum of items squared
// in one go with a help of Aggregate
var stat = matrix
.OfType<double>()
.Aggregate((n: 0, s: 0.0, ss: 0.0), (s, a) => (s.n + 1, s.s + a, s.ss + a * a));
double stdDev = Math.Sqrt(stat.ss / stat.n - stat.s * stat.s / stat.n / stat.n);
In order not to deal with such constructions, you can implement extension methods:
public static partial class Array2dExtensions {
public static double Average(this double[,] matrix) {
if (matrix == null)
throw new ArgumentNullException(nameof(matrix));
return matrix
.OfType<double>()
.Average();
}
public static double Variance(this double[,] matrix) {
if (matrix == null)
throw new ArgumentNullException(nameof(matrix));
var stat = matrix
.OfType<double>()
.Aggregate((n: 0, s: 0.0, ss: 0.0), (s, a) =>
(s.n + 1, s.s + a, s.ss + a * a));
return stat.ss / stat.n - stat.s * stat.s / stat.n / stat.n;
}
}
Having this implemented you can put it as if array has Average and Variance methods:
double mean = matrix.Average();
double stdDev = Math.Sqrt(matrix.Variance());
Related
I'm taking the Coursera machine learning course right now and I cant get my gradient descent linear regression function to minimize. I use: one dependent variable, an intercept, and four values of x and y, therefore the equations are fairly simple. The final value of the Gradient Decent equation varies wildly depending on the initial values of alpha and beta and I cant figure out why.
I've only been coding for about two weeks, so my knowledge is limited to say the least, please keep this in mind if you take the time to help.
using System;
namespace LinearRegression
{
class Program
{
static void Main(string[] args)
{
Random rnd = new Random();
const int N = 4;
//We randomize the inital values of alpha and beta
double theta1 = rnd.Next(0, 100);
double theta2 = rnd.Next(0, 100);
//Values of x, i.e the independent variable
double[] x = new double[N] { 1, 2, 3, 4 };
//VAlues of y, i.e the dependent variable
double[] y = new double[N] { 5, 7, 9, 12 };
double sumOfSquares1;
double sumOfSquares2;
double temp1;
double temp2;
double sum;
double learningRate = 0.001;
int count = 0;
do
{
//We reset the Generalized cost function, called sum of squares
//since I originally used SS to
//determine if the function was minimized
sumOfSquares1 = 0;
sumOfSquares2 = 0;
//Adding 1 to counter for each iteration to keep track of how
//many iterations are completed thus far
count += 1;
//First we calculate the Generalized cost function, which is
//to be minimized
sum = 0;
for (int i = 0; i < (N - 1); i++)
{
sum += Math.Pow((theta1 + theta2 * x[i] - y[i]), 2);
}
//Since we have 4 values of x and y we have 1/(2*N) = 1 /8 = 0.125
sumOfSquares1 = 0.125 * sum;
//Then we calcualte the new alpha value, using the derivative of
//the cost function.
sum = 0;
for (int i = 0; i < (N - 1); i++)
{
sum += theta1 + theta2 * x[i] - y[i];
}
//Since we have 4 values of x and y we have 1/(N) = 1 /4 = 0.25
temp1 = theta1 - learningRate * 0.25 * sum;
//Same for the beta value, it has a different derivative
sum = 0;
for (int i = 0; i < (N - 1); i++)
{
sum += (theta1 + theta2 * x[i]) * x[i] - y[i];
}
temp2 = theta2 - learningRate * 0.25 * sum;
//WE change the values of alpha an beta at the same time, otherwise the
//function wont work
theta1 = temp1;
theta2 = temp2;
//We then calculate the cost function again, with new alpha and beta values
sum = 0;
for (int i = 0; i < (N - 1); i++)
{
sum += Math.Pow((theta1 + theta2 * x[i] - y[i]), 2);
}
sumOfSquares2 = 0.125 * sum;
Console.WriteLine("Alpha: {0:N}", theta1);
Console.WriteLine("Beta: {0:N}", theta2);
Console.WriteLine("GCF Before: {0:N}", sumOfSquares1);
Console.WriteLine("GCF After: {0:N}", sumOfSquares2);
Console.WriteLine("Iterations: {0}", count);
Console.WriteLine(" ");
} while (sumOfSquares2 <= sumOfSquares1 && count < 5000);
//we end the iteration cycle once the generalized cost function
//cannot be reduced any further or after 5000 iterations
Console.ReadLine();
}
}
}
There are two bugs in the code.
First, I assume that you would like to iterate through all the element in the array. So rework the for loop like this: for (int i = 0; i < N; i++)
Second, when updating the theta2 value the summation is not calculated well. According to the update function it should be look like this: sum += (theta1 + theta2 * x[i] - y[i]) * x[i];
Why the final values depend on the initial values?
Because the gradient descent update step is calculated from these values. If the initial values (Starting Point) are too big or too small, then it will be too far away from the final values (Final Value). You could solve this problem by:
Increasing the iteration steps (e.g. 5000 to 50000): gradient descent algorithm has more time to converge.
Decreasing the learning rate (e.g. 0.001 to 0.01): gradient descent update steps are bigger, therefore it converges faster. Note: if the learning rate is too small, then it is possible to step through the global minimum.
The slope (theta2) is around 2.5 and the intercept (theta1) is around 2.3 for the given data. I have created a github project to fix your code and i have also added a shorter solution using LINQ. It is 5 line of codes. If you are curious check it out here.
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;
}
}
I am trying to learn C#, and as an exercise for myself, I have coded the Box-Muller method, and am now trying to plot a histogram of my simulated datapoints to check if the data looks fairly normal.
For creating the histogram, I am following this guide here: http://www.i-programmer.info/programming/uiux/2756-getting-started-with-net-charts.html
I have included my code so far below. My problem is that I get squiggly red lines under "chart1" in the main method, and I get the error "The name 'chart1' does not exist in the current context'. There seem to be nothing from the guide that I am missing. Can anyone clear up what I am missing?
Best regards.
using System;
using System.Windows.Forms.DataVisualization.Charting;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
double[] normalData = new double[200];
for (int i = 1; i <= 100; i++)
{
Tuple<double, double> Z = BoxMuller(i);
normalData[2 * i - 2] = Z.Item1;
normalData[2 * i - 1] = Z.Item2;
//Console.WriteLine("{0} {1}", normalData[2 * i - 2], normalData[2 * i - 1]);
}
//Trying to make a simple histogram (to begin with)
DataPoint Dp = new DataPoint();
Dp.SetValueY(3);
chart1.Series.Clear();
chart1.Series.Add("My Data");
}
static Tuple<double, double> BoxMuller(int i)
{
Random rand = new Random(i);
double U1 = rand.NextDouble();
double U2 = rand.NextDouble();
double R = -2 * Math.Log(U1);
double V = 2 * Math.PI * U2;
double Z1 = Math.Sqrt(R) * Math.Cos(V);
double Z2 = Math.Sqrt(R) * Math.Sin(V);
Tuple<double, double> tuple = new Tuple<double, double>(Z1, Z2);
return tuple;
}
}
}
I'm trying to implement a Discrete Fourier Transformation algorithm for a project I'm doing in school. But creating a class is seeming to be difficult(which it shouldn't be).
I'm using Visual Studio 2012.
Basically I need a class called Complex to store the two values I get from a DFT; The real portion and the imaginary portion.
This is what I have so far for that:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SoundEditor_V3
{
public class Complex
{
public double real;
public double im;
public Complex()
{
real = 0;
im = 0;
}
}
}
The problem is that it doesn't recognize the constructor as a constructor, I'm just learning C#, but I looked it up online and this is how it's supposed to look.
But it recognizes my constructor as a method.
Why is that?
Am I creating the class wrong?
It's doing the same thing for my Fourier class as well. So each time I try to create a
Fourier object and then use it's method...there is no such thing.
example, I do this:
Fourier fou = new Fourier();
fou.DFT(s, N, amp, 0);
and it tells me fou is a 'field' but is used like a 'type'
why is it saying that?
Here is the code for my Fourier class as well:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SoundEditor_V3
{
public class Fourier
{
//FOURIER
//N = number of samples
//s is the array of samples(data)
//amp is the array where the complex result will be written to
//start is the where in the array to start
public void DFT(byte[] s, int N, ref Complex[] amp, int start)
{
Complex tem = new Complex();
int f;
int t;
for (f = 0; f < N; f++)
{
tem.real = 0;
tem.im = 0;
for (t = 0; t < N; t++)
{
tem.real += s[t + start] * Math.Cos(2 * Math.PI * t * f / N);
tem.im -= s[t + start] * Math.Sin(2 * Math.PI * t * f / N);
}
amp[f].real = tem.real;
amp[f].im = tem.im;
}
}
//INVERSE FOURIER
public void IDFT(Complex[] A, ref int[] s)
{
int N = A.Length;
int t, f;
double result;
for (t = 0; t < N; t++)
{
result = 0;
for (f = 0; f < N; f++)
{
result += A[f].real * Math.Cos(2 * Math.PI * t * f / N) - A[f].im * Math.Sin(2 * Math.PI * t * f / N);
}
s[t] = (int)Math.Round(result);
}
}
}
}
I'm very much stuck at the moment, any and all help would be appreciated. Thank you.
edit:
this is where I'm trying to access all my classes:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SoundEditor_V3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string filename;
NAudio.Wave.WaveStream waveStream;
private NAudio.Wave.DirectSoundOut sout = null;
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog open = new OpenFileDialog();
open.Filter = "Wave File (*.wav)|*.wav";
if (open.ShowDialog() != DialogResult.OK)
{
return;
}
waveStream = new NAudio.Wave.WaveFileReader(open.FileName);
filename = open.FileName;
sout = new NAudio.Wave.DirectSoundOut();
sout.Init(new NAudio.Wave.WaveChannel32(waveStream));
}
//Play
private void Play_btn_Click(object sender, EventArgs e)
{
sout.Play();
}
//Stop
private void Stop_btn_Click(object sender, EventArgs e)
{
sout.Stop();
waveStream.Position = 0;
}
//Pause
private void Pause_btn_Click(object sender, EventArgs e)
{
sout.Pause();
}
//display fourier
//N = number of samples(length of array)
//s is the array of samples(data)
//amp is the array where the complex result will be written to
//start is the where in the array to start
static int N = 8;
byte[] s = {1,2,3,4,5,6,7,8};
Complex[] amp = new Complex[N];
Fourier xfo = new Fourier();
//xfo.DFT(s, N, amp, 0);
}
}
This call should be inside a method. As of now, it looks its directly under a class.
//xfo.DFT(s, N, amp, 0);
Also add ref for amp. (As the void DFT(...., ref Complex[] amp,....) takes a ref amp parameter.
xfo.DFT(s, N, ref amp, 0);
Oh boy, so much room to improve.
First you are using the class Complex as a struct, in fact there is no need for it to be a class, so make it a struct:
public struct Complex
{
public double Imaginary;
public double Real;
}
No constructor needed, the default constructor (which the compilers add) will set the fields to their default value according to their type, and for double the default value is 0.0 (which is what you are assigning to them anyway*).
I have also renamed im to Imaginary, and don't tell me you have to type more because you got intellisense. If you didn't go download Mono Develop or Visual Studio Express. Oh, I can feel your thinking: we shouldn't relay on the tools. Well, that's right, and that is another reason to write code that is easy to read, even for those unfamiliar with the concepts (it also makes searching easier).
*: I want to note that 0 is a intenger literal and 0.0 is double, but the compiler reconizes this and optimizes the conversion away, so it is the same for practical purposes.
Let's move to your fourier class, first the method DFT, which I copy below (with the names of the fields of Complex renamed):
//FOURIER
//N = number of samples
//s is the array of samples(data)
//amp is the array where the complex result will be written to
//start is the where in the array to start
public void DFT(byte[] s, int N, ref Complex[] amp, int start)
{
Complex tem = new Complex();
int f;
int t;
for (f = 0; f < N; f++)
{
tem.real = 0;
tem.im = 0;
for (t = 0; t < N; t++)
{
tem.real += s[t + start] * Math.Cos(2 * Math.PI * t * f / N);
tem.im -= s[t + start] * Math.Sin(2 * Math.PI * t * f / N);
}
amp[f].real = tem.real;
amp[f].im = tem.im;
}
}
The first thing to notice is that you say that N is the number of samples and s is the samples array. Well, if you have an array you can query the size of the array, which is a good idea even if you want to allow to only process a portion of the array (I think you want that). But, really N and s?
Look, it's like magic:
//FOURIER
//amp is the array where the complex result will be written to
//start is the where in the array to start
public void DFT(byte[] samples, int samplesCount, ref Complex[] amp, int start)
{
Complex tem = new Complex();
int f;
int t;
for (f = 0; f < samplesCount; f++)
{
tem.Real = 0;
tem.Imaginary = 0;
for (t = 0; t < samplesCount; t++)
{
tem.Imaginary += samples[t + start] * Math.Cos(2 * Math.PI * t * f / samplesCount);
tem.Imaginary -= samples[t + start] * Math.Sin(2 * Math.PI * t * f / samplesCount);
}
amp[f].Real = tem.Real;
amp[f].Imaginary = tem.Imaginary;
}
}
Ok, next you say that amp is the output. Well if it is the output, why don't you make it te method return it?
Bam!
//FOURIER
//start is the where in the array to start
Complex[] DFT(byte[] samples, int samplesCount, int start)
{
var = new Complex[samplesCount];
Complex tem = new Complex();
int f;
int t;
for (f = 0; f < samplesCount; f++)
{
tem.Real = 0;
tem.Imaginary = 0;
for (t = 0; t < samplesCount; t++)
{
tem.Imaginary += samples[t + start] * Math.Cos(2 * Math.PI * t * f / samplesCount);
tem.Imaginary -= samples[t + start] * Math.Sin(2 * Math.PI * t * f / samplesCount);
}
result[f].Real = tem.Real;
result[f].Imaginary = tem.Imaginary;
}
return result;
}
Does it really need to be an array? I think this is a good oportunity to use the yield keyword and return IEnumerable<Complex>. But I'll take that you want, in deed, an array.
Now, may be you didn't want to return an array. May be you want to just modify portions of a preexisting array. In that case you should start checking your bounds. And even if that were true, you don't need ref at all! because the array is a reference type. It is a reference passed by value, if you cannot wrap your mind around that idea, just trust me, you can modify the contents of an array and see that reflected outside without ref... passing a reference by reference allows you to change the reference by another one, and you are not doing that.
To demostrate:
void Main()
{
var x = new int[1];
Do(x);
Console.WriteLine(x);
}
void Do (int[] array)
{
array[0] = 1;
}
The output of the previous program (compiled with LinqPad) is "1".
But let's get back to your code, shall we?
I don't know what are f and t. Thankfully I knew that im was imaginary (it was, right?). So I'll not rename them. But I'll move their definition to the loops:
Complex[] DFT(byte[] samples, int samplesCount, int start)
{
var result = new Complex[samplesCount];
Complex tem = new Complex();
for (int f = 0; f < samplesCount; f++)
{
tem.Real = 0;
tem.Imaginary = 0;
for (int t = 0; t < samplesCount; t++)
{
tem.Imaginary += samples[t + start] * Math.Cos(2 * Math.PI * t * f / samplesCount);
tem.Imaginary -= samples[t + start] * Math.Sin(2 * Math.PI * t * f / samplesCount);
}
result[f].Real = tem.Real;
result[f].Imaginary = tem.Imaginary;
}
return result;
}
Note my use of the var keyword. With it the compiler assigns the type of the variable to the type of what I'm using to initialize it. So in this case result is a Complex[] but I did not have to write that twice in the code.
And finally, that part where you copy the contents of the Complex object, well, I'll change that too. Why? Because Complex now is a struct, and structs are valuetypes. So it's content gets copied instead of a reference.
//FOURIER
//start is the where in the array to start
Complex[] DFT(byte[] samples, int samplesCount, int start)
{
var result = new Complex[samplesCount];
Complex tem = new Complex();
for (int f = 0; f < samplesCount; f++)
{
tem.Real = 0;
tem.Imaginary = 0;
for (int t = 0; t < samplesCount; t++)
{
tem.Imaginary += samples[t + start] * Math.Cos(2 * Math.PI * t * f / samplesCount);
tem.Imaginary -= samples[t + start] * Math.Sin(2 * Math.PI * t * f / samplesCount);
}
result[f] = tem;
}
return result;
}
I know you really want to proccess just a part of your array. But bear with me... you will learn a few things and that code will be useful anyway.
The next thing I want is to return an IEnumerable<Complex> which is an interface that represents anything that can be iterated to get objects of type Complex. I'll also use the yield keyword.
Additionally I've got rid of sampleCount and use samples.Length instead.
Just look how beautiful it gets:
//FOURIER
public IEnumerable<Complex> DFT(byte[] samples, int startIndex)
{
int samplesLength = samples.Length;
for (int f = 0; f < samplesLength; f++)
{
Complex resultItem = new Complex();
for (int t = 0; t < samplesLength; t++)
{
resultItem.Real += samples[t + startIndex] * Math.Cos(2 * Math.PI * t * f / samplesLength);
resultItem.Imaginary -= samples[t + startIndex] * Math.Sin(2 * Math.PI * t * f / samplesLength);
}
yield return resultItem;
}
}
In fact, I'll get rid of startIndex too (we are not checking bounds anyway*).
*: that is, we are not checking if the index are inside the array size. I know, I know, you was going to add them later... probably.
Anyway, you are learning some C# here.
//FOURIER
public IEnumerable<Complex> DFT(byte[] samples)
{
int samplesLength = samples.Length;
for (int f = 0; f < samplesLength; f++)
{
Complex resultItem = new Complex();
for (int t = 0; t < samplesLength; t++)
{
resultItem.Real += samples[t] * Math.Cos(2 * Math.PI * t * f / samplesLength);
resultItem.Imaginary -= samples[t] * Math.Sin(2 * Math.PI * t * f / samplesLength);
}
yield return resultItem;
}
}
Well, the next thing that bothers me is the fact that the class Fourier has no state (it has no fields, or any variable which value is persisted... somehow). So, make it a static class with a static method:
public static class Fourier
{
//FOURIER
public static IEnumerable<Complex> DFT(byte[] samples)
{
int samplesLength = samples.Length;
for (int f = 0; f < samplesLength; f++)
{
Complex resultItem = new Complex();
for (int t = 0; t < samplesLength; t++)
{
resultItem.Real += samples[t] * Math.Cos(2 * Math.PI * t * f / samplesLength);
resultItem.Imaginary -= samples[t] * Math.Sin(2 * Math.PI * t * f / samplesLength);
}
yield return resultItem;
}
}
}
Of course you notice I haven't added IDFT. That one is homework.
Now, let's see how you use it. In my case I created a ConsoleApplication, just to have it up and running fast (no time wasted designing a GUI).
What I want is to call Fourier.DFT which I can without an object of type Fourier because it is static (In fact I cannot create an object of type Fourier because it is static).
This method recieves an argument of type byte[]. That one will be new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }. And that method will return something I can use to iterate over to get objects of type Complex. So I want to put it a loop.
This is how my code looks like:
class Program
{
static void Main(string[] args)
{
//display fourier
foreach (var item in Fourier.DFT(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }))
{
Console.WriteLine(item);
}
}
}
Now... the output is... drum roll...
Well, I can't see it, I forgot Console.ReadLine(); but after adding that the output is...
Namespace.Complex
Namespace.Complex
Namespace.Complex
Namespace.Complex
Namespace.Complex
Namespace.Complex
Namespace.Complex
Namespace.Complex
Wait, what? It happens that I haven't told it how to convert an object of type Complex to string. So let's add that:
public struct Complex
{
public double Imaginary;
public double Real;
public override string ToString()
{
return string.Format("Complex [Real: {0}, Imaginary: {1}]", Real, Imaginary);
}
}
Now my output is:
Complex [Real: 36, Imaginary: 0]
Complex [Real: -4, Imaginary: 9,65685424949238]
Complex [Real: -4, Imaginary: 4]
Complex [Real: -4, Imaginary: 1,65685424949239]
Complex [Real: -4, Imaginary: -3,91874033223161E-15]
Complex [Real: -4,00000000000001, Imaginary: -1,65685424949239]
Complex [Real: -4,00000000000002, Imaginary: -4,00000000000001]
Complex [Real: -3,99999999999997, Imaginary: -9,65685424949237]
Is the output correct? I have no freaking idea! I have to learn more about Fourier (but it looks legit).
After verification, the output is correct.
One final note: Step trhoug the code with a debuger, you may find a surprise (hint: yield).
You need a method, try this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SoundEditor_V3
{
public class Complex
{
public double real;
public double im;
public Complex()
{
real = 0;
im = 0;
}
public Setval (double newReal, double newIm)
{
real = newReal;
im = newIm;
}
}
}
In regards to your other class, where is the constructor? ;)
Thank you for all your help; I actually ended up figuring everything out.
I couldn't access methods in the area I was trying to access them in. I had to put them inside a method block because this was all being coded inside a form.
That's my understanding anyway.
But again, thank you for all your suggestions, they were all helpful.
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.