Fraction Calculator error - c#

The problem is that the expression 1/4 + 2 1/2 displays the result of 2 3/8 instead of 2 3/4. The same thing goes to the expression 1/8 + 2 1/2, the result displays 2 3/8 as well. Please help me with this. Thanks!
class FractionDemo
{
static void Main(string[] args)
{
Fraction firstfraction = new Fraction();
Fraction secondfraction = new Fraction();
firstfraction.Numerator = 1;
firstfraction.Denominator = 4;
secondfraction.Numerator = 1;
secondfraction.Denominator = 8;
secondfraction.WholeNumber = 2;
Fraction add = new Fraction();
add = firstfraction + secondfraction;
Console.Write("\n {0}/{1}", firstfraction.Numerator, firstfraction.Denominator);
Console.WriteLine(" + {0}/{1} = {2}/{3}", secondfraction.Numerator, secondfraction.Denominator, add.Numerator, add.Denominator);
Console.Write("\n {0}/{1}", firstfraction.Numerator, firstfraction.Denominator);
Console.WriteLine(" + {0} {1}/{2} = {3} {4}/{5}", secondfraction.WholeNumber, secondfraction.Numerator,secondfraction.WholeNumber, add.WholeNumber, add.Numerator, add.Denominator);
Console.Write("\n {0}/{1}", firstfraction.Numerator, secondfraction.Denominator);
Console.WriteLine(" + {0} {1}/{2} = {3} {4}/{5}", secondfraction.WholeNumber, secondfraction.Numerator, secondfraction.WholeNumber, add.WholeNumber, add.Numerator, add.Denominator);
Console.ReadLine();
}
public class Fraction
{
private int wholenumber;
private int numerator;
private int denominator;
public int WholeNumber
{
get
{
return wholenumber;
}
set
{
wholenumber = value;
}
}
public int Numerator
{
get
{
return numerator;
}
set
{
numerator = value;
}
}
public int Denominator
{
get
{
return denominator;
}
set
{
denominator = value;
if (denominator > 0)
{
denominator = value;
}
else
{
denominator = 1;
}
}
}
public Fraction(int wholenumber, int numerator, int denominator)
: this(numerator, denominator)
{
WholeNumber = wholenumber;
}
public Fraction(int numerator, int denominator)
{
WholeNumber = 0;
Numerator = numerator;
Denominator = denominator;
}
public Fraction()
{
WholeNumber = 0;
Numerator = 0;
Denominator = 1;
}
public int gcd()
{
int x = Numerator;
int y = Denominator;
int m;
if (x > y)
m = y;
else
m = x;
for (int i = m; i >= 1; i--)
{
if (x % i == 0 && y % i == 0)
{
return i;
}
}
return 1;
}
public void Reduce()
{
int gcdNum = gcd();
if (gcdNum != 0)
{
Numerator = Numerator / gcdNum;
Denominator = Denominator / gcdNum;
}
if (Denominator < 0)
{
Denominator = Denominator * -1;
Numerator = Numerator * -1;
}
convertFraction();
}
public void convertFraction()
{
WholeNumber = Numerator / Denominator;
Numerator = Numerator % Denominator;
}
public static Fraction operator +(Fraction firstfraction, Fraction secondfraction)
{
int firstNum = (firstfraction.WholeNumber * firstfraction.Denominator) + firstfraction.Numerator;
int secondNum = (secondfraction.WholeNumber * secondfraction.Denominator) + secondfraction.Numerator;
Fraction Result = new Fraction();
Result.Numerator = firstNum * secondfraction.Denominator + firstfraction.Denominator * secondNum;
Result.Denominator = firstfraction.Denominator * secondfraction.Denominator;
Result.Reduce();
return Result;
}
}
}

Your Fraction is correct. For first example you should use:
firstfraction.Numerator = 1;
firstfraction.Denominator = 4;
secondfraction.Numerator = 1;
secondfraction.Denominator = 2;
secondfraction.WholeNumber = 2;
Then you'll get 2 3/4

Related

Calculate the sequence : n!/ (1+1/2+1/3+...+1/n)

Calculate the following sum
1!/1 + 2!/(1+1/2) + 3!/(1+1/2+1/3) + ... + n!/ (1+1/2+1/3+...+1/n), where n > 0.
public static double GetSumSix(int n)
{
double i, result = 0.0;
static double factorial(double n)
{
double res = 1;
for (double i = 2; i <= n; i++)
res *= i;
return res;
}
for (i = 1.0; i <= n; i++)
{
result += factorial(i) / (1.0 / i);
}
return result;
}
Help me please , I don't understand why is my solution not working?
Your denominator logic is incorrect. You could create another function to work out what '1/1+1/2+...+1/n' is and use that in the denominator? right now your code will work out 1+2!*2+3!*3+...
You could actually use something similar to your factorial method
static double GetDenominator(double n)
{
double res = 1;
for (double i = 2; i <= n; i++)
//insert code here
return res;
}
The Lemon's answer is correct, you're not accumulating the denominator of the sequence so what you were calculating was:
f(n) = 1!/1 + 2!/(1/2) + 3!/(1/3) + ... n!/(1/n)
Since both the numerator and denominator of each term are algorithmically linked to the values in the prior term you can simply update them each pass through the loop. This is (slightly) faster and fairly easy to read.
public static double GetSumSix(int n)
{
double factorial = 1;
double denominator = 1;
double accum = 1;
for (int i = 2; i <= n; i++)
{
factorial *= i;
denominator += 1.0d/i;
accum += factorial / denominator;
}
return accum;
}
Your logic is not correct as per your question , also your code won't execute as you have a function inside your GetSumSix function. I have put some helping points in below code so you will understand how the logic works.
using System;
public class Program
{
public static void Main()
{
var Calculate = GetSumSix(3);
Console.WriteLine("The Answer is " + Calculate);
}
public static double GetSumSix(int n)
{
int i;
double result = 0.0;
int factorial = 1;
string calculatedFormula = String.Empty;
string FinalFormat = String.Empty;
//Find n!
for(int x=n;x>=1;x--)
{
factorial *= x;
}
// Find Denominator (1+1/2+1/3+…+1/n)
for (i = 1.0; i <= n; i++)
{
result += GetDenominator(i, ref calculatedFormula);
FinalFormat += calculatedFormula;
}
result = factorial/result;
Console.WriteLine("Calculated Formula is:"+ factorial +"/(" + FinalFormat +")When N is :" + n);
return result;
}
public static double GetDenominator(double n, ref string cal)
{
if (n == 1)
{
cal += n + "+ ";
return 1;
}
else
{
cal = "1/" + n + "+ ";
return 1 / n;
}
}
}
Thanks.

How can I find the Least Common Multiple of two fractions?

Precondition: The fractions are expressed in simplest form and denom != 0.
Improper fractions are allowed.
Postcondition: Returns the LCM (as a fraction) of the two fractions.
Using System.Numerics.BigInteger for my numerator and denominator.
This is what I currently have, but I think this works only for BigInteger...not my custom made Fraction class:
public static Fraction LCM(Fraction a, Fraction b)
{
Fraction frac1, frac2;
if (a > b)
{
frac1 = a; frac2 = b;
}
else
{
frac1 = b; frac2= a;
}
for (Fraction i = new Fraction(); i < frac2; i = i.Add(new Fraction()))
{
if (frac1.Multiply(i).Divide(frac2).Simplify().num == 1)
{
return i.Multiply(frac1);
}
}
return frac1.Multiply(frac2);
}
new Fraction() returns 1/1
Fraction Class:
public class Fraction
{
public BigInteger num, denom;
public Fraction power, coef;
public Fraction()
{
num = denom = 1;
}
public Fraction(BigInteger n)
{
num = n;
denom = 1;
}
public Fraction(BigInteger num, BigInteger denom)
{
this.num = num;
this.denom = denom;
if (GCD(BigInteger.Abs(num), BigInteger.Abs(denom)) != 1 || (num > 0 && denom < 0)
|| (num < 0 && denom < 0))
{
BigInteger n = Simplify().num;
BigInteger d = Simplify().denom;
this.num = n;
this.denom = d;
}
}
public Fraction(BigInteger num, BigInteger denom, Fraction power)
{
Fraction n = new Fraction(num, denom);
coef = new Fraction();
this.num = n.num;
this.denom = n.denom;
this.power = power.Simplify();
if (power.num != 1)
{
Fraction n2 = n.Pow(power.num);
this.num = n2.num;
this.denom = n2.denom;
this.power = new Fraction(BigInteger.One, power.denom);
}
if (this.power.denom != 1)
{
Fraction n3 = SimplifyRadical();
this.num = n3.num;
this.denom = n3.denom;
if (n3.coef != null)
{
coef = new Fraction(n3.coef.num, n3.coef.denom);
}
if (n3.power != null)
{
this.power = n3.power.Simplify();
}
}
}
public Fraction(Fraction n, Fraction power)
{
BigInteger newNum = n.num;
BigInteger newDenom = n.denom;
Fraction n2 = new Fraction(newNum, newDenom, power);
num = n2.num;
denom = n2.denom;
this.power = n2.power;
if (n2.coef != null)
{
coef = n2.coef;
}
}
public Fraction Multiply(Fraction f)
{
Fraction product;
if (power != null || f.power != null)
{
if (power == null)
{
power = new Fraction(1);
}
if (f.power == null)
{
f.power = new Fraction(1);
}
Fraction LCMPower = LCM(power, f.power);
product = new Fraction(new Fraction(num, denom).Pow(power.Multiply(LCMPower.Reciprocate()).num).Multiply(new Fraction(f.num, f.denom).Pow(f.power.Multiply(LCMPower.Reciprocate()).num)), LCMPower);
}
else
{
product = new Fraction(BigInteger.Multiply(num, f.num), BigInteger.Multiply(denom, f.denom));
}
if(coef != null || f.coef != null)
{
if(coef != null && f.coef != null)
{
product.coef = coef.Multiply(f.coef);
}
else if(coef != null && f.coef == null)
{
product.coef = coef;
}
else if (coef == null && f.coef != null)
{
product.coef = f.coef;
}
}
return product;
}
public Fraction Divide(Fraction f)
{
return Multiply(f.Reciprocate());
}
public Fraction Reciprocate()
{
if (power != null)
{
return new Fraction(denom, num, power);
}
else
{
return new Fraction(denom, num);
}
}
public Fraction Raise(Fraction p)
{
Fraction newP = p;
if (p.num < 0)
{
Fraction n = Reciprocate();
num = n.num;
denom = n.denom;
newP = new Fraction(BigInteger.Abs(p.num), BigInteger.Abs(p.denom));
}
if (power != null)
{
return new Fraction(num, denom, power.Multiply(newP));
}
else
{
return new Fraction(num, denom, p);
}
}
public Fraction Pow(BigInteger p)
{
BigInteger newNum = num;
BigInteger newDenom = denom;
bool reverse = false;
if (p < 0)
{
p = -p;
reverse = true;
}
else if (p == 0)
{
return new Fraction();
}
if (power != null)
{
if (reverse)
{
return new Fraction(newDenom, newNum, power.Multiply(new Fraction(p)));
}
else
{
return new Fraction(newNum, newDenom, power.Multiply(new Fraction(p)));
}
}
else
{
for (int i = 1; i < p; i++)
{
newNum = BigInteger.Multiply(newNum, num);
newDenom = BigInteger.Multiply(newDenom, denom);
}
if (reverse)
{
return new Fraction(newDenom, newNum);
}
else
{
return new Fraction(newNum, newDenom);
}
}
}
public bool IsOne()
{
Fraction ONE = new Fraction();
return num == 1 && denom == 1;
}
public bool IsZero()
{
Fraction ZERO = new Fraction(0);
return num == 0;
}
public static List<BigInteger> PrimeFactorization(BigInteger Fraction)
{
BigInteger prime = new BigInteger(2);
List<BigInteger> primesArr = new List<BigInteger>();
while (Fraction >= prime * prime)
{
if (Fraction % prime == 0)
{
primesArr.Add(prime);
Fraction /= prime;
}
else
{
prime++;
}
}
primesArr.Add(Fraction);
return primesArr;
}
public static BigInteger GCD(BigInteger num1, BigInteger num2)
{
while (num1 != 0 && num2 != 0)
{
if (num1 > num2)
{
num1 %= num2;
}
else
{
num2 %= num1;
}
}
if (num1 == 0)
{
return num2;
}
else
{
return num1;
}
}
public static Fraction LCM(Fraction a, Fraction b)
{
a = a.Simplify();
b = b.Simplify();
Fraction num1, num2;
if (a > b)
{
num1 = a; num2 = b;
}
else
{
num1 = b; num2 = a;
}
for (Fraction i = new Fraction(); i < num2; i = i.Add(new Fraction()))
{
if (num1.Multiply(i).Divide(num2).Simplify().num == 1)
{
return i.Multiply(num1);
}
}
return num1.Multiply(num2);
}
public static bool operator >(Fraction num1, Fraction num2)
{
return Comparison(num1, num2) > 0;
}
public static bool operator <(Fraction num1, Fraction num2)
{
return Comparison(num1, num2) < 0;
}
public static bool operator >=(Fraction num1, Fraction num2)
{
return Comparison(num1, num2) >= 0;
}
public static bool operator <=(Fraction num1, Fraction num2)
{
return Comparison(num1, num2) <= 0;
}
public static int Comparison(Fraction num1, Fraction num2)
{
Fraction newNum1 = new Fraction();
Fraction newNum2 = new Fraction();
newNum1.num = num1.num * num2.denom;
newNum1.denom = num1.denom * num2.denom;
newNum2.num = num2.num * num1.denom;
newNum2.denom = num2.denom * num1.denom;
if (newNum1.num < newNum2.num)
{
return -1;
}
else if (newNum1.num == newNum2.num)
{
return 0;
}
else if (newNum1.num > newNum2.num)
{
return 1;
}
return 0;
}
public Fraction Simplify()
{
bool nnum = false, ndenom = false;
if (num < 0)
{
nnum = true;
num = -num;
}
if (denom < 0)
{
ndenom = true;
denom = -denom;
}
BigInteger divisor = GCD(num, denom);
BigInteger numNew = num / divisor;
BigInteger denomNew = denom / divisor;
if (nnum)
{
numNew = -numNew;
}
if (ndenom)
{
numNew = -numNew;
}
if (power != null)
{
numNew = SimplifyPower().num;
denomNew = SimplifyPower().denom;
Fraction powerNew = SimplifyPower().power;
return new Fraction(numNew, denomNew, powerNew);
}
return new Fraction(numNew, denomNew);
}
private Fraction SimplifyPower()
{
return new Fraction(Pow(power.num), new Fraction(BigInteger.One, power.denom));
}
private Fraction SimplifyRadical()
{
Fraction final = new Fraction();
final.coef = new Fraction();
List<BigInteger> pN = PrimeFactorization(num);
List<BigInteger> pD = PrimeFactorization(denom);
List<BigInteger> pNDupes = FractionOfDupes(pN);
List<BigInteger> pDDupes = FractionOfDupes(pD);
int index = 0;
int position = 0;
for (int i = 0; i < pNDupes.Count; i++)
{
if (pNDupes[i] >= power.denom)
{
BigInteger pow = pNDupes[i] / power.denom;
BigInteger powLeft = pNDupes[i] - power.denom * pow;
final.coef = final.coef.Multiply(new Fraction(pN[position]).Raise(new Fraction(pow)));
final.num *= new Fraction(pN[index], 1, new Fraction(powLeft, 1)).num;
position += (int)pNDupes[i];
}
else
{
final.num *= new Fraction(pN[index], 1, new Fraction(pNDupes[i], 1)).num;
}
index += 2;
}
index = 0;
position = 0;
for (int i = 0; i < pDDupes.Count; i++)
{
if (pDDupes[i] >= power.denom)
{
BigInteger pow = pDDupes[i] / power.denom;
BigInteger powLeft = pDDupes[i] - power.denom * pow;
final.coef = final.coef.Divide(new Fraction(pD[position]).Raise(new Fraction(pow)));
final.denom *= new Fraction(pD[index], 1, new Fraction(powLeft, 1)).num;
position += (int)pDDupes[i];
}
else
{
final.denom *= new Fraction(pD[index], 1, new Fraction(pDDupes[i], 1)).num;
}
index += 2;
}
final.power = power;
return final;
}
private List<BigInteger> NumberOfDupes(List<BigInteger> a)
{
List<BigInteger> l = new List<BigInteger>();
List<BigInteger> final = new List<BigInteger>();
foreach (BigInteger el in a)
{
l.Add(el);
}
int index = 0;
for (int i = 0; i < l.Count; i++)
{
BigInteger ele = l[i];
final.Add(1);
l.RemoveAt(i);
for (int j = 0; j < l.Count; j++)
{
if (ele == l[j])
{
final[index]++;
l.RemoveAt(j);
j--;
}
}
i--;
index++;
}
return final;
}
public void Print(bool printLn)
{
if (coef != null && !(coef.num == 1 && coef.denom == 1))
{
PrintHelper(coef);
if (!(num == 1 && denom == 1))
{
Console.Write("*");
}
}
if (!IsOne() || coef == null)
{
PrintHelper(this);
}
if (power != null && !power.IsOne() && !IsOne())
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Write("^");
PrintHelper(power);
}
if (printLn)
{
Console.WriteLine();
}
Console.ForegroundColor = ConsoleColor.Gray;
}
private void PrintHelper(Fraction n)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.Write("[");
Console.ForegroundColor = ConsoleColor.Gray;
Console.Write(n.num);
Console.ForegroundColor = ConsoleColor.Green;
if (n.denom != 1)
{
Console.Write("/");
Console.ForegroundColor = ConsoleColor.Gray;
Console.Write(n.denom);
Console.ForegroundColor = ConsoleColor.Green;
Console.Write("]");
}
else
{
Console.Write("]");
}
}
public Fraction Add(Fraction a)
{
Fraction newNum1 = new Fraction(Multiply(new Fraction(a.denom, a.denom)).num, denom * a.denom);
Fraction newNum2 = new Fraction(a.Multiply(new Fraction(denom, denom)).num, denom * a.denom);
return new Fraction(newNum1.num + newNum2.num, denom * a.denom);
}
}
Your integer algorithm is right, but it's based on integer arithmetic, on the idea a division, sometimes results in a natural number, and sometimes in a natural number and a Rest. This is not possible with fraction. You can dived them as you want - you will always get a new fraction - there will never be a Rest.
So this algorithm is not applicable. I found a formula, that makes a conversion:
lcm(a/b, c/d) = lcm(a,b,c,d)/lcm(b,d).
lcm(a,b,c,d)=lcm(lcm(a,b),lcm(c,d)).
So all together is
lcm(lcm(a,b),lcm(c,d))/lcm(b,d)
So you got 4 calls to the integer version of lcm, to do one lcm for a fraction.
Do not Modify your int-version of LCM.
The Fraction version would be
public static BigInteger LCM(Fraction a, Fraction b)
{
return lcm(lcm(a.num, a.denom), lcm(b.num, b.denom))/lcm(a.denom, b.denom);
}
But this will only find least natural number common multiple.
The result of lcm(1/4, 1/8) will be 1, not 1/4 as one may assume.

why a list<long[]> variable automatically changes with another variable?

I have two variables: long[] nextState and List<long[]> TabuList.
I use this code to add items to TabuList:
TabuList.add(nextState);
or this:
TabuList.insert(Index, nexState);
but the problem is that after either of these operations, all of TabuList’s items automatically convert to the current value of nextState.
my complete code is:
class TabuSearch
{
private long[] current { get; set; }
private double Delta;
private Random rnd = new Random();
int foundLists = 0;
public TabuSearch()
{
current = new long[Convert.ToInt32(num_list1)];
}
public long[] TabuMOSA3Objectives(long[] c)
{
assign(current, c);
long[] nextState = new long[Convert.ToInt32(num_list1)];
List<long[]> TabuList = new List<long[]>();
double proba;
double alpha = 0.969;
double temperature = 500.0;
double epsilon = 0.0001;
short domination_st;
int iter = 0;
while (temperature > epsilon)
{
iter++;
Delta = 1;
assign(nextState, GenerateNextState(primaryList, current));
domination_st = CheckDomination3Objective(nextState, current);
try { var tmp = TabuList.Find(x => x == nextState); if (tmp == null) foundLists = 0; else foundLists = tmp.Count(); }
catch { }
if (foundLists == 0)
{
if (domination_st > 0)
{
assign(current, nextState);
}
else // domination_st < 0
{
proba = rnd.NextDouble();
if (proba < 1 / (1 + Math.Exp(Delta * temperature)))
{
assign(current, nextState);
}
else
{
if (TabuList.Count == 10)
TabuList.RemoveAt(0);
assign(nextState, TabuList);
}
}
}
//cooling proces on every iteration
temperature *= alpha;
}
return current;
}
}
static void assign(long[] c, long[] n)
{
for (int i = 0; i < c.Length; i++)
c[i] = n[i];
}
static void assign(long[] item, List<long[]> list)
{
list.Add(item);
}

Returning Nth Fibonacci number the sequence?

I have a question on my homework for class and I need to know how to return nth number of Fibonacci sequence using iteration (no recursion allowed).
I need some tips on how to do this so I can better understand what I am doing wrong. I output to the console in my program.cs, hence it being absent in the code below.
// Q1)
//
// Return the Nth Fibonacci number in the sequence
//
// Input: uint n (which number to get)
// Output: The nth fibonacci number
//
public static UInt64 GetNthFibonacciNumber(uint n)
{
// Return the nth fibonacci number based on n.
if (n == 0 || n == 1)
{
return 1;
}
// The basic Fibonacci sequence is
// 1, 1, 2, 3, 5, 8, 13, 21, 34...
// f(0) = 1
// f(1) = 1
// f(n) = f(n-1) + f(n-2)
///////////////
//my code is below this comment
uint a = 0;
uint b = 1;
for (uint i = 0; i < n; i++)
{
n = b + a;
a = b;
b = n;
}
return n;
:)
static ulong Fib(int n)
{
double sqrt5 = Math.Sqrt(5);
double p1 = (1 + sqrt5) / 2;
double p2 = -1 * (p1 - 1);
double n1 = Math.Pow(p1, n + 1);
double n2 = Math.Pow(p2, n + 1);
return (ulong)((n1 - n2) / sqrt5);
}
Just for a little fun you could do it with an infinite Fibonacci list and some IEnumerable extensions
public IEnumerable<int> Fibonacci(){
var current = 1;
var b = 0;
while(true){
var next = current + b;
yield return next;
b = current;
current = next;
}
}
public T Nth<T>(this IEnumerable<T> seq, int n){
return seq.Skip.(n-1).First();
}
Getting the nth number would then be
Fibonacci().Nth(n);
public static int GetNthFibonacci(int n)
{
var previous = -1;
var current = 1;
int index = 1;
int element = 0;
while (index++ <= n)
{
element = previous + current;
previous = current;
current = element;
}
return element;
}
I think this should do the trick:
uint a = 0;
uint b = 1;
uint c = 1;
for (uint i = 0; i < n; i++)
{
c = b + a;
a = b;
b = c;
}
return c;
public IEnumerable<BigInteger> FibonacciBig(int maxn)
{
BigInteger Fn=1;
BigInteger Fn_1=1;
BigInteger Fn_2=1;
yield return Fn;
yield return Fn;
for (int i = 3; i < maxn; i++)
{
Fn = Fn_1 + Fn_2;
yield return Fn;
Fn_2 = Fn_1;
Fn_1 = Fn;
}
}
you can get the n-th Number by
FibonacciBig(100000).Skip(n).First();
This is the solution for your homework, you should start from 3 because you already have numbers for f1 and f2 (first two numbers). Please note that there is no point in getting 0th Fibonacci number.
public static UInt64 GetNthFibonacciNumber(uint n)
{
// Return the nth fibonacci number based on n.
if (n == 1 || n == 2)
{
return 1;
}
uint a = 1;
uint b = 1;
uint c;
for (uint i = 3; i <= n; i++)
{
c = b + a;
a = b;
b = c;
}
return c;
}
public static UInt64 GetNthFibonacciNumber(uint n)
{
if (n == 0 || n == 1)
{
return 1;
}
UInt64 a = 1, b = 1;
uint i = 2;
while (i <= n)
{
if (a > b) b += a;
else a += b;
++i;
}
return (a > b) ? a : b;
}
public static List<int> PrintFibonacci(int number)
{
List<int> result = new List<int>();
if (number == 0)
{
result.Add(0);
return result;
}
else if (number == 1)
{
result.Add(0);
return result;
}
else if (number == 2)
{
result.AddRange(new List<int>() { 0, 1 });
return result;
}
else
{
//if we got thus far,we should have f1,f2 and f3 as fibonacci numbers
int f1 = 0,
f2 = 1;
result.AddRange(new List<int>() { f1, f2 });
for (int i = 2; i < number; i++)
{
result.Add(result[i - 1] + result[i - 2]);
}
}
return result;
}
Only 2 variables are needed (declaring one in a for loop counts too).
public int NthFib(int n)
{
int curFib = 0;
int nextFib = 1;
while (--n > 0)
{
nextFib += curFib;
curFib = nextFib - curFib;
}
return curFib;
}
If you want to see the sequence to n change it to:
public IEnumerable<int> NthFib(int n)
{
int curFib = 0;
int nextFib = 1;
while (n-- > 0)
{
yield return curFib;
nextFib += curFib;
curFib = nextFib - curFib;
}
}

Neural Network, Getting output less then 1

I am trying to create a neural network for the function y=e^(-(x-u)^2)/(2*o^2)) where u = 50 and o = 15.
I must train my neural network so I can find the 2 x's for each y. I have created the folling code, it seems to learn it nicely, but once I test the outputs go I only get numbers around 0.99 to 1 where I should get 25 and 75 and I just can't see why. My best guess is that my error correction is wrong, but can't find the error. The neural network uses back-propagation.
The test code and training set
class Program
{
static void Main(string[] args)
{
args = new string[] {
"c:\\testTrain.csv",
"c:\\testValues.csv"
};
// Output File
string fileTrainPath = null;
string fileValuesPath = null;
if (args.Length > 0)
{
fileTrainPath = args[0];
if (File.Exists(fileTrainPath))
File.Delete(fileTrainPath);
fileValuesPath = args[1];
if (File.Exists(fileValuesPath))
File.Delete(fileValuesPath);
}
double learningRate = 0.1;
double u = 50;
double o = 15;
Random rand = new Random();
Network net = new Network(1, 8, 4, 2);
NetworkTrainer netTrainer = new NetworkTrainer(learningRate, net);
List<TrainerSet> TrainerSets = new List<TrainerSet>();
for(int i = 0; i <= 20; i++)
{
double random = rand.NextDouble();
TrainerSets.Add(new TrainerSet(){
Inputs = new double[] { random },
Outputs = getX(random, u, o)
});
}
// Train Network
string fileTrainValue = String.Empty;
for (int i = 0; i <= 10000; i++)
{
if (i == 5000)
{ }
double error = netTrainer.RunEpoch(TrainerSets);
Console.WriteLine("Epoch " + i + ": Error = " + error);
if(fileTrainPath != null)
fileTrainValue += i + "," + learningRate + "," + error + "\n";
}
if (fileTrainPath != null)
File.WriteAllText(fileTrainPath, fileTrainValue);
// Test Network
string fileValuesValue = String.Empty;
for (int i = 0; i <= 100; i++)
{
double y = rand.NextDouble();
double[] dOutput = getX(y, u, o);
double[] Output = net.Compute(new double[] { y });
if (fileValuesPath != null)
fileValuesValue += i + "," + y + "," + dOutput[0] + "," + dOutput[1] + "," + Output[0] + "," + Output[1] + "\n";
}
if (fileValuesPath != null)
File.WriteAllText(fileValuesPath, fileValuesValue);
}
public static double getResult(int x, double u, double o)
{
return Math.Exp(-Math.Pow(x-u,2)/(2*Math.Pow(o,2)));
}
public static double[] getX(double y, double u, double o)
{
return new double[] {
u + Math.Sqrt(2 * Math.Pow(o, 2) * Math.Log(1/y)),
u - Math.Sqrt(2 * Math.Pow(o, 2) * Math.Log(1/y)),
};
}
}
The code behind the network
public class Network
{
protected int inputsCount;
protected int layersCount;
protected NetworkLayer[] layers;
protected double[] output;
public int Count
{
get
{
return layers.Count();
}
}
public NetworkLayer this[int index]
{
get { return layers[index]; }
}
public Network(int inputsCount, params int[] neuronsCount)
{
this.inputsCount = Math.Max(1, inputsCount);
this.layersCount = Math.Max(1, neuronsCount.Length);
layers = new NetworkLayer[neuronsCount.Length];
for (int i = 0; i < layersCount; i++)
layers[i] = new NetworkLayer(neuronsCount[i],
(i == 0) ? inputsCount : neuronsCount[i - 1]);
}
public virtual double[] Compute(double[] input)
{
output = input;
foreach (NetworkLayer layer in layers)
output = layer.Compute(output);
return output;
}
}
public class NetworkLayer
{
protected int inputsCount = 0;
protected int neuronsCount = 0;
protected Neuron[] neurons;
protected double[] output;
public Neuron this[int index]
{
get { return neurons[index]; }
}
public int Count
{
get { return neurons.Length; }
}
public int Inputs
{
get { return inputsCount; }
}
public double[] Output
{
get { return output; }
}
public NetworkLayer(int neuronsCount, int inputsCount)
{
this.inputsCount = Math.Max( 1, inputsCount );
this.neuronsCount = Math.Max( 1, neuronsCount );
neurons = new Neuron[this.neuronsCount];
output = new double[this.neuronsCount];
// create each neuron
for (int i = 0; i < neuronsCount; i++)
neurons[i] = new Neuron(inputsCount);
}
public virtual double[] Compute(double[] input)
{
// compute each neuron
for (int i = 0; i < neuronsCount; i++)
output[i] = neurons[i].Compute(input);
return output;
}
}
public class Neuron
{
protected static Random rand = new Random((int)DateTime.Now.Ticks);
public int Inputs;
public double[] Input;
public double[] Weights;
public double Output = 0;
public double Threshold;
public double Error;
public Neuron(int inputs)
{
this.Inputs = inputs;
Weights = new double[inputs];
for (int i = 0; i < inputs; i++)
Weights[i] = rand.NextDouble() * 0.5;
}
public double Compute(double[] inputs)
{
Input = inputs;
double e = 0.0;
for (int i = 0; i < inputs.Length; i++)
e += Weights[i] * inputs[i];
e -= Threshold;
return (Output = sigmoid(e));
}
private double sigmoid(double value)
{
return (1 / (1 + Math.Exp(-1 * value)));
//return 1 / (1 + Math.Exp(-value));
}
}
My Trainer
public class NetworkTrainer
{
private Network network;
private double learningRate = 0.1;
public NetworkTrainer(double a, Network network)
{
this.network = network;
this.learningRate = a;
}
public double Run(double[] input, double[] output)
{
network.Compute(input);
return CorrectErrors(output);
}
public double RunEpoch(List<TrainerSet> sets)
{
double error = 0.0;
for (int i = 0, n = sets.Count; i < n; i++)
error += Run(sets[i].Inputs, sets[i].Outputs);
// return summary error
return error;
}
private double CorrectErrors(double[] desiredOutput)
{
double[] errorLast = new double[desiredOutput.Length];
NetworkLayer lastLayer = network[network.Count - 1];
for (int i = 0; i < desiredOutput.Length; i++)
{
// S(p)=y(p)*[1-y(p)]*(yd(p)-y(p))
lastLayer[i].Error = lastLayer[i].Output * (1-lastLayer[i].Output)*(desiredOutput[i] - lastLayer[i].Output);
errorLast[i] = lastLayer[i].Error;
}
// Calculate errors
for (int l = network.Count - 2; l >= 0; l--)
{
for (int n = 0; n < network[l].Count; n++)
{
double newError = 0;
for (int np = 0; np < network[l + 1].Count; np++)
{
newError += network[l + 1][np].Weights[n] * network[l + 1][np].Error;
}
network[l][n].Error = newError;
}
}
// Update Weights
// w = w + (a * input * error)
for (int l = network.Count - 1; l >= 0; l--)
{
for (int n = 0; n < network[l].Count; n++)
{
for (int i = 0; i < network[l][n].Inputs; i++)
{
// deltaW = a * y(p) * s(p)
double deltaW = learningRate * network[l][n].Output * network[l][n].Error;
network[l][n].Weights[i] += deltaW;
}
}
}
double returnError = 0;
foreach (double e in errorLast)
returnError += e;
return returnError;
}
}
For regression problems your output layer should have the identity (or at least a linear) activation function. This way you don't have to scale your output. The derivative of the identity function is 1 and thus the derivative dE/da_i for the output layer is y-t (lastLayer[i].Output - desiredOutput[i]).

Categories