How can I use a Fast Magnitude calculation for 3 values (instead of using square root)? (+/- 3% is good enough)
public void RGBToComparison(Color32[] color)
{
DateTime start = DateTime.Now;
foreach (Color32 i in color)
{
var r = PivotRgb(i.r / 255.0);
var g = PivotRgb(i.g / 255.0);
var b = PivotRgb(i.b / 255.0);
var X = r * 0.4124 + g * 0.3576 + b * 0.1805;
var Y = r * 0.2126 + g * 0.7152 + b * 0.0722;
var Z = r * 0.0193 + g * 0.1192 + b * 0.9505;
var LB = PivotXyz(X / 95.047);
var AB = PivotXyz(Y / 100);
var BB = PivotXyz(Z / 108.883);
var L = Math.Max(0, 116 * AB - 16);
var A = 500 * (LB - AB);
var B = 200 * (AB - BB);
totalDifference += Math.Sqrt((L-LT)*(L-LT) + (A-AT)*(A-AT) + (B-BT)*(B-BT));
}
totalDifference = totalDifference / color.Length;
text.text = "Amount of Pixels: " + color.Length + " Time(MilliSeconds):" + DateTime.Now.Subtract(start).TotalMilliseconds + " Score (0 to 100)" + (totalDifference).ToString();
RandomOrNot();
}
private static double PivotRgb(double n)
{
return (n > 0.04045 ? Math.Pow((n + 0.055) / 1.055, 2.4) : n / 12.92) * 100.0;
}
private static double PivotXyz(double n)
{
return n > 0.008856 ? CubicRoot(n) : (903.3 * n + 16) / 116;
}
private static double CubicRoot(double n)
{
return Math.Pow(n, 1.0 / 3.0);
}
This is the important part: totalDifference += Math.Sqrt((L-LT)*(L-LT) + (A-AT)*(A-AT) + (B-BT)*(B-BT));
I know there are FastMagnitude calculations online, but all the ones online are for two values, not three. For example, could i use the difference between the values to get a precise answer? (By implementing the difference value into the equation, and if the difference percentage-wise is big, falling back onto square root?)
Adding up the values and iterating the square root every 4 pixels is a last resort that I could do. But firstly, I want to find out if it is possible to have a good FastMagnitude calculation for 3 values.
I know I can multi-thread and parllelize it, but I want to optimize my code before I do that.
If you just want to compare the values, why not leave the square root out and work with the length squared?
Or use the taylor series of the square root of 1+x and cut off early :)
Related
Recently my friends and I decided to make a multi-functional calculator to automatically find
the roots of quadratic equations.
It wasn't that challenging after all, so we decided to go onto the next level, to make a calculator for a cubic equation.
(ax^3 + bx^2 + cx + d)
However, we stumbled across some trivial problems, and no matter how hard we tried, the results are still the same.
we are beginners in terms of coding, so we're not sure if we are actually making some stupid mistakes here
but at least we want to learn something from others.
Basically, we have tried a lot of combinations of different cubic equations, or even re-coding the whole thing. The problem is that the results we yield are always wrong, but only for the real parts of the second root and third root.
For a better understanding, we have tried 9x^3 + 8x^2 + 7x + 6, as an example.
The correct answer, according to a cubic equation calculator website, is
(The website)
First root = -0.87285
Second root = -0.00802 + 0.87391 i
Third root = -0.00802 - 0.87391 i
However, our result to this equation is :
First root = -0.87285
Second root = -0.2963 + 0.87391 i
Third root = -0.2963 + -0.87391 i
It is apparently noticeable that only parts of the second and third roots are wrong.
We have tried finding similar threads to help, but those are a little bit too difficult for us to understand or those problems are not the same as ours.
We look forward to finding the solution and the causes to this problem.
We have separated the formulas for finding the roots of a cubic equation into 5 parts.
(rootp1-rootp5)
The formulas are coded according to the formulas that can be found in the Chinese version of Wikipedia's page of Cubic equation.
(The formulas)
We have also rounded the real parts of the roots to 5 digits.
(Some code lines might be redundant, but as I have mentioned, we are new to coding)
Code (C#) :
using System;
using System.Numerics;
namespace ComplexNumbers
{
public class ComplexNo
{
public static void Main()
{
Console.WriteLine("Cubic Equation Calculator :");
Console.Write("Insert first coefficient : ");
double a = Convert.ToDouble(Console.ReadLine());
Console.Write("Insert second coefficient : ");
double b = Convert.ToDouble(Console.ReadLine());
Console.Write("Insert third coefficient : ");
double c = Convert.ToDouble(Console.ReadLine());
Console.Write("Insert constant : ");
double d = Convert.ToDouble(Console.ReadLine());
Console.WriteLine(" ");
Console.WriteLine("Solve for " + a + "x" + "^3 " + b + "x^2 " + c + "x " + d + " :");
double rootp1 = -(b / (3 * a));
double rootp2 = (b * c / (6 * Math.Pow(a, 2))) - (Math.Pow(b, 3) / (27 * Math.Pow(a, 3))) - (d / (2 * a));
double rootp3 = (c / (3 * a)) - (Math.Pow(b, 2) / (9 * Math.Pow(a, 2)));
Complex root1 = rootp1 + Math.Cbrt(rootp2 + Math.Sqrt(Math.Pow(rootp2, 2) + Math.Pow(rootp3, 3))) +
Math.Cbrt(rootp2 - Math.Sqrt(Math.Pow(rootp2, 2) + Math.Pow(rootp3, 3)));
Complex rootp4 = new Complex(-1 / 2, Math.Sqrt(3) / 2);
Complex rootp5 = new Complex(-1 / 2, -(Math.Sqrt(3) / 2));
Complex root2 = rootp1 + (rootp4 * Math.Cbrt(rootp2 + Math.Sqrt(Math.Pow(rootp2, 2) + Math.Pow(rootp3, 3)))) +
(rootp5 * Math.Cbrt(rootp2 - Math.Sqrt(Math.Pow(rootp2, 2) + Math.Pow(rootp3, 3))));
Complex root3 = rootp1 + (rootp5 * Math.Cbrt(rootp2 + Math.Sqrt(Math.Pow(rootp2, 2) + Math.Pow(rootp3, 3)))) +
(rootp4 * Math.Cbrt(rootp2 - Math.Sqrt(Math.Pow(rootp2, 2) + Math.Pow(rootp3, 3))));
Console.WriteLine(" ");
Console.WriteLine("Results :");
Console.WriteLine("First Root :");
string root1rp = Convert.ToString(Math.Round(root1.Real, 5));
string root1ip = Convert.ToString(Math.Round(root1.Imaginary, 5));
Console.WriteLine(root1rp + " + " + root1ip + "i");
Console.WriteLine("Second Root :");
string root2rp = Convert.ToString(Math.Round(root2.Real, 5));
string root2ip = Convert.ToString(Math.Round(root2.Imaginary, 5));
Console.WriteLine(root2rp + " + " + root2ip + "i");
Console.WriteLine("Third Root :");
string root3rp = Convert.ToString(Math.Round(root3.Real, 5));
string root3ip = Convert.ToString(Math.Round(root3.Imaginary, 5));
Console.WriteLine(root3rp + " + " + root3ip + "i");
Console.ReadLine();
}
}
}
(Sorry for making this thread so long and my bad grammar)
The problem is with this line Complex rootp4 = new Complex(-1 / 2, Math.Sqrt(3) / 2);. -1/2 uses integer division and evaluates to 0.
This code will work.
Console.WriteLine(" ");
Console.WriteLine("Solve for " + a + "x" + "^3 " + b + "x^2 " + c + "x " + d + " :");
double minusBover3a = -(b / (3 * a));
double rootp2 = (b * c / (6 * Math.Pow(a, 2))) - (Math.Pow(b, 3) / (27 * Math.Pow(a, 3))) - (d / (2 * a));
double rootp3 = (c / (3 * a)) - (Math.Pow(b, 2) / (9 * Math.Pow(a, 2)));
double bigCubeRootPlus = Math.Cbrt(rootp2 + Math.Sqrt(Math.Pow(rootp2, 2) + Math.Pow(rootp3, 3)));
double bigCubeRootMinus = Math.Cbrt(rootp2 - Math.Sqrt(Math.Pow(rootp2, 2) + Math.Pow(rootp3, 3)));
// ** THIS IS THE PROBLEM. "-1/2" uses integer division, so this complex has 0 for real part
Complex complexPlus = new Complex(-1.0 / 2, Math.Sqrt(3) / 2);
Complex complexMinus = new Complex(-1.0 / 2, -(Math.Sqrt(3) / 2));
Complex root1 = minusBover3a + bigCubeRootPlus + bigCubeRootMinus;
Complex root2 = minusBover3a + complexPlus * bigCubeRootPlus + complexMinus * bigCubeRootMinus;
Complex root3 = minusBover3a + complexMinus * bigCubeRootPlus + complexPlus * bigCubeRootMinus;
I admit I haven't tried your code, but you may have a casting issue in the math in your original calculations. Try this:
double rootp2 = ((double)b * (double)c / (6D * Math.Pow(a, 2D))) - (Math.Pow(b, 3D) / (27D * Math.Pow(a, 3D))) - ((double)d / (2D * (double)a));
If that makes a difference, you'd have to propagate a similar change (cast all variables as (double) and inline constants as double with D) through the other calculations.
The following is an alternative to your code:
// from https://www.daniweb.com/programming/software-development/
// code/454493/solving-the-cubic-equation-using-the-complex-struct
// algorithm described in
// https://en.wikipedia.org/wiki/Cubic_equation#General_cubic_formula
const int NRoots = 3;
double SquareRootof3 = Math.Sqrt(3);
// the 3 cubic roots of 1
var CubicUnity = new List<Complex>(NRoots)
{ new Complex(1, 0),
new Complex(-0.5, -SquareRootof3 / 2.0),
new Complex(-0.5, SquareRootof3 / 2.0) };
// intermediate calculations
double DELTA = 18 * a * b * c * d
- 4 * b * b * b * d
+ b * b * c * c
- 4 * a * c * c * c
- 27 * a * a * d * d;
double DELTA0 = b * b - 3 * a * c;
double DELTA1 = 2 * b * b * b
- 9 * a * b * c
+ 27 * a * a * d;
Complex DELTA2 = -27 * a * a * DELTA;
Complex C = Complex.Pow((DELTA1 + Complex.Pow(DELTA2, 0.5)) / 2, 1 / 3.0);
for (int i = 0; i < NRoots; i++)
{
Complex M = CubicUnity[i] * C;
Complex Root = -1.0 / (3 * a) * (b + M + DELTA0 / M);
Console.WriteLine();
Console.WriteLine($"Root {i+1}:");
Console.WriteLine($"Real {Root.Real:0.#####}");
Console.WriteLine($"Imaginary {Root.Imaginary:0.#####}i");
}
I'm looking for a high precision solution to find the center point of a circle from 3 data points on a canvas (x,y). I found this example in the attached screenshot above, now I'm using the Math.NET package to solve the equation and I'm comparing the results against this online tool: https://planetcalc.com/8116/.
However, when I calculate the radius its completely off and often a negative number???
using MathNet.Numerics.LinearAlgebra.Double.Solvers;
using MathNet.Numerics.LinearAlgebra.Double;
using System;
namespace ConsoleAppTestBed
{
class Program
{
static void Main(string[] args)
{
var dataPoints = new double[,]
{
{ 5, 80 },
{ 20, 100 },
{ 40, 140 }
};
var fitter = new CircleFitter();
var result = fitter.Fit(dataPoints);
var x = -result[0];
var y = -result[1];
var c = result[2];
Console.WriteLine("Center Point:");
Console.WriteLine(x);
Console.WriteLine(y);
Console.WriteLine(c);
//// (x^2 + y^2 - c^2)
var radius = Math.Pow(x, 2) + Math.Pow(y, 2) - Math.Pow(c, 2);
//// sqrt((x^2 + y^2 - c^2))
radius = Math.Sqrt(radius);
Console.WriteLine("Radius:");
Console.WriteLine(radius);
Console.ReadLine();
}
public class CircleFitter
{
public double[] Fit(double[,] v)
{
var xy1 = new double[] { v[0,0], v[0,1] };
var xy2= new double[] { v[1, 0], v[1, 1] };
var xy3 = new double[] { v[2, 0], v[2, 1] };
// Create Left Side Matrix of Equation
var a = CreateLeftSide_(xy1);
var b = CreateLeftSide_(xy2);
var c = CreateLeftSide_(xy3);
var matrixA = DenseMatrix.OfArray(new[,]
{
{ a[0], a[1], a[2] },
{ b[0], b[1], b[2] },
{ c[0], c[1], c[2] }
});
// Create Right Side Vector of Equation
var d = CreateRightSide_(xy1);
var e = CreateRightSide_(xy2);
var f = CreateRightSide_(xy3);
double[] vector = { d, e, f };
var vectorB = Vector<double>.Build.Dense(vector);
// Solve Equation
var r = matrixA.Solve(vectorB);
var result = r.ToArray();
return result;
}
//2x, 2y, 1
public double[] CreateLeftSide_(double[] d)
{
return new double[] { (2 * d[0]), (2 * d[1]) , 1};
}
// -(x^2 + y^2)
public double CreateRightSide_(double[] d)
{
return -(Math.Pow(d[0], 2) + Math.Pow(d[1], 2));
}
}
}
}
Any ideas?
Thanks in advance.
The solution to your problem is here: The NumberDecimalDigits property
Code:
using System;
using System.Globalization;
namespace ConsoleApp1
{
class Program
{
static void Main()
{
double x1 = 1, y1 = 1;
double x2 = 2, y2 = 4;
double x3 = 5, y3 = -3;
findCircle(x1, y1, x2, y2, x3, y3);
Console.ReadKey();
}
static void findCircle(double x1, double y1,
double x2, double y2,
double x3, double y3)
{
NumberFormatInfo setPrecision = new NumberFormatInfo();
setPrecision.NumberDecimalDigits = 3; // 3 digits after the double point
double x12 = x1 - x2;
double x13 = x1 - x3;
double y12 = y1 - y2;
double y13 = y1 - y3;
double y31 = y3 - y1;
double y21 = y2 - y1;
double x31 = x3 - x1;
double x21 = x2 - x1;
double sx13 = (double)(Math.Pow(x1, 2) -
Math.Pow(x3, 2));
double sy13 = (double)(Math.Pow(y1, 2) -
Math.Pow(y3, 2));
double sx21 = (double)(Math.Pow(x2, 2) -
Math.Pow(x1, 2));
double sy21 = (double)(Math.Pow(y2, 2) -
Math.Pow(y1, 2));
double f = ((sx13) * (x12)
+ (sy13) * (x12)
+ (sx21) * (x13)
+ (sy21) * (x13))
/ (2 * ((y31) * (x12) - (y21) * (x13)));
double g = ((sx13) * (y12)
+ (sy13) * (y12)
+ (sx21) * (y13)
+ (sy21) * (y13))
/ (2 * ((x31) * (y12) - (x21) * (y13)));
double c = -(double)Math.Pow(x1, 2) - (double)Math.Pow(y1, 2) -
2 * g * x1 - 2 * f * y1;
double h = -g;
double k = -f;
double sqr_of_r = h * h + k * k - c;
// r is the radius
double r = Math.Round(Math.Sqrt(sqr_of_r), 5);
Console.WriteLine("Center of a circle: x = " + h.ToString("N", setPrecision) +
", y = " + k.ToString("N", setPrecision));
Console.WriteLine("Radius: " + r.ToString("N", setPrecision));
}
}
}
I have just converted William Li's answer to Swift 5 for
those who like to cmd+C and cmd+V like me :)
func calculateCircle(){
let x1:Float = 0
let y1:Float = 0
let x2:Float = 0.5
let y2:Float = 0.5
let x3:Float = 1
let y3:Float = 0
let x12 = x1 - x2
let x13 = x1 - x3
let y12 = y1 - y2
let y13 = y1 - y3
let y31 = y3 - y1
let y21 = y2 - y1
let x31 = x3 - x1
let x21 = x2 - x1
let sx13 = pow(x1, 2) - pow(x3, 2)
let sy13 = pow(y1, 2) - pow(y3, 2)
let sx21 = pow(x2, 2) - pow(x1, 2)
let sy21 = pow(y2, 2) - pow(y1, 2)
let f = ((sx13) * (x12)
+ (sy13) * (x12)
+ (sx21) * (x13)
+ (sy21) * (x13))
/ (2 * ((y31) * (x12) - (y21) * (x13)))
let g = ((sx13) * (y12)
+ (sy13) * (y12)
+ (sx21) * (y13)
+ (sy21) * (y13))
/ (2 * ((x31) * (y12) - (x21) * (y13)))
let c = -pow(x1, 2) - pow(y1, 2) - 2 * g * x1 - 2 * f * y1
let h = -g
let k = -f
let r = sqrt(h * h + k * k - c)
print("center x = \(h)")
print("center y = \(k)")
print("r = \(r)")
}
Updated Answer
The equation for radius is incorrect; it should be (not c squared):
which is why you get incorrect values for the radius.
The original answer was incorrect, but it is still 'interesting'.
(Incorrect) Original Answer
The cause of the problematic calculation is not solely due to the precision of the numbers, but more because problem is ill-conditioned. If you look at the three points and where they are located on the circle, you'll see that they are bunched on a small segment of the circumference. When the points are so close to each other, it is a tough ask to find the circle's centre and radius accurately.
So the intermediate calculations, which will have small rounding errors, result in hugely exaggerated errors.
You can see the ill-conditioned nature of the problem by adding the ConditionNumber() method.
// Solve Equation
Console.WriteLine(matrixA.ConditionNumber()); // <<< Returns 5800 -> Big!
var r = matrixA.Solve(vectorB); // Existing code
A large result indicates an ill-conditioned problem. In this case a value of 5800 is returned, which is large. You might get better results using Gaussian Elimination with partial pivoting, but it still does not address the fact that the basic problem is ill-conditioned, which is why you get wildly incorrect answers.
In this case,this is the array which serves as coefficients and degrees which first value having no degree.
double[] arr = { 12, 2, 3 ,4};
I then made a method to print the above array in terms of polynomial equation.
It gives output in type string as follows :
2x^2 + 3x^3 + 4x^4 + 12
I want to a function which takes an argument x and then solve the above polynomial with respect to value of x.
How can I do that?
Any kind of help will be appreciated!.
Edit: Question Solved
To evaluate it you can simply sum the power values times the coefficients. Using LINQ, that's one line:
double result = arr.Select((c,i) => c * Math.Pow(x, i)).Sum();
Here i is the index into your array, it starts at zero, so x^0 = 1 * 12 == 12 etc.
You can also do it without LINQ like this:
List<string> debug = new List<string>();
double y = 1.0;
result = 0.0;
for (int i = 0; i < arr.Length; i++)
{
debug.Add($"{arr[i]} * x^{i}");
result = result + arr[i] * y;
y = y * x;
}
Console.WriteLine(string.Join(" + ", debug));
Console.WriteLine(result);
Which, for x=3 outputs:
12 * x^0 + 2 * x^1 + 3 * x^2 + 4 * x^3
153
Same result as LINQ.
This is what I created:
for (int i = 1; i < degree.Length; i++)
{
result_first += degree[i] * Math.Pow(x, degree[i]);
}
result_first += degree[0];
It works perfectly.
I have this function wrote in C# to calc the sin(x). But when I try with x = 3.14, the printed result of sin X is NaN (not a number),
but when debugging, its is very near to 0.001592653
The value is not too big, neither too small. So how could the NaN appear here?
static double pow(double x, int mu)
{
if (mu == 0)
return 1;
if (mu == 1)
return x;
return x * pow(x, mu - 1);
}
static double fact(int n)
{
if (n == 1 || n == 0)
return 1;
return n * fact(n - 1);
}
static double sin(double x)
{
var s = x;
for (int i = 1; i < 1000; i++)
{
s += pow(-1, i) * pow(x, 2 * i + 1) / fact(2 * i + 1);
}
return s;
}
public static void Main(String[] param)
{
try
{
while (true)
{
Console.WriteLine("Enter x value: ");
double x = double.Parse(Console.ReadLine());
var sinX = sin(x);
Console.WriteLine("Sin of {0} is {1}: " , x , sinX);
Console.ReadLine();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
It fails because both pow(x, 2 * i + 1) and fact(2 * i + 1) eventually return Infinity.
In my case, it's when x = 4, i = 256.
Note that pow(x, 2 * i + 1) = 4 ^ (2 * 257) = 2.8763090157797054523668883052624395737887631663 × 10^309 - a stupidly large number which is just over the max value of a double, which is approximately 1.79769313486232 x 10 ^ 308.
You might be interested in just using Math.Sin(x)
Also note that fact(2 * i + 1) = 513! =an even more ridiculously large number which is more than 10^1000 times larger than the estimated number of atoms in the observable universe.
When x == 3.14 and i == 314 then you get Infinity:
?pow(-1, 314)
1.0
?pow(x, 2 * 314 + 1)
Infinity
? fact(2 * 314 + 1)
Infinity
The problem here is an understanding of floating point representation of 'real' numbers.
Double numbers while allowing a large range of values only has a precision of 15 to 17 decimal digits.
In this example we are calculating a value between -1 and 1.
We calculate the value of the sin function by using the series expansion of it which is basically a the sum of terms. In that expansion the terms become smaller and smaller as we go along.
When the terms have reached a value less than 1e-17 adding them to what is already there will not make any difference. This is so because we only have 52 bit of precision which are used up by the time we get to a term of less than 1e-17.
So instead of doing a constant 1000 loops you should do something like this:
static double sin(double x)
{
var s = x;
for (int i = 1; i < 1000; i++)
{
var term = pow(x, 2 * i + 1) / fact(2 * i + 1);
if (term < 1e-17)
break;
s += pow(-1, i) * term;
}
return s;
}
could anyone help me restart my program from line 46 if the user enters 1 (just after the comment where it states that the next code is going to ask the user for 2 inputs) and if the user enters -1 end it. I cannot think how to do it. I'm new to C# any help you could give would be great!
class Program
{
static void Main(string[] args)
{
//Displays data in correct Format
List<float> inputList = new List<float>();
TextReader tr = new StreamReader("c:/users/tom/documents/visual studio 2010/Projects/DistanceCalculator3/DistanceCalculator3/TextFile1.txt");
String input = Convert.ToString(tr.ReadToEnd());
String[] items = input.Split(',');
Console.WriteLine("Point Latitude Longtitude Elevation");
for (int i = 0; i < items.Length; i++)
{
if (i % 3 == 0)
{
Console.Write((i / 3) + "\t\t");
}
Console.Write(items[i]);
Console.Write("\t\t");
if (((i - 2) % 3) == 0)
{
Console.WriteLine();
}
}
Console.WriteLine();
Console.WriteLine();
// Ask for two inputs from the user which is then converted into 6 floats and transfered in class Coordinates
Console.WriteLine("Please enter the two points that you wish to know the distance between:");
string point = Console.ReadLine();
string[] pointInput = point.Split(' ');
int pointNumber = Convert.ToInt16(pointInput[0]);
int pointNumber2 = Convert.ToInt16(pointInput[1]);
Coordinates distance = new Coordinates();
distance.latitude = (Convert.ToDouble(items[pointNumber * 3]));
distance.longtitude = (Convert.ToDouble(items[(pointNumber * 3) + 1]));
distance.elevation = (Convert.ToDouble(items[(pointNumber * 3) + 2]));
distance.latitude2 = (Convert.ToDouble(items[pointNumber2 * 3]));
distance.longtitude2 = (Convert.ToDouble(items[(pointNumber2 * 3) + 1]));
distance.elevation2 = (Convert.ToDouble(items[(pointNumber2 * 3) + 2]));
//Calculate the distance between two points
const double PIx = 3.141592653589793;
const double RADIO = 6371;
double dlat = ((distance.latitude2) * (PIx / 180)) - ((distance.latitude) * (PIx / 180));
double dlon = ((distance.longtitude2) * (PIx / 180)) - ((distance.longtitude) * (PIx / 180));
double a = (Math.Sin(dlat / 2) * Math.Sin(dlat / 2)) + Math.Cos((distance.latitude) * (PIx / 180)) * Math.Cos((distance.latitude2) * (PIx / 180)) * (Math.Sin(dlon / 2) * Math.Sin(dlon / 2));
double angle = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
double ultimateDistance = (angle * RADIO);
Console.WriteLine("The distance between your two points is...");
Console.WriteLine(ultimateDistance);
//Repeat the program if the user enters 1, end the program if the user enters -1
Console.WriteLine("If you wish to calculate another distance type 1 and return, if you wish to end the program, type -1.");
Console.ReadLine();
if (Convert.ToInt16(Console.ReadLine()) == 1);
{
//here is where I need it to repeat
}
bool exit = false;
do
{
Console.WriteLine("Please enter the two points that you wish to know the distance between:");
...
Console.WriteLine("If you wish to calculate another distance type 1 and return, if you wish to end the program, type -1.");
string input;
do
{
input = Console.ReadLine().Trim();
}
while (input != "1" && input != "-1");
if (input == -1) exit = true;
}
while (!exit);
But you would do much better to think about pushing logic into methods and functions such that you program is built up of much smaller building blocks.
You should be aiming towards something like this:
bool exit = false;
do
{
Point[] points = ReadCoordinates();
Whatever result = CalculateWhatever();
DisplayResults(results);
exit = ShouldExit();
}
while (!exit);
This makes the outer loop of your program self documenting and the methods self explanatory.
if (Convert.ToInt16(Console.ReadLine()) == 1);
{
Main(args)
}
That's quite an odd thing to do.
Have you looked into the while loop?
You could make a method of the above structure and loop it, while userinput equals 1
if it equals -1, call the following statement
Application.Exit()
Can use Goto to make the program loop on user input.
public static void Main(string[] args)
{
RestartApplication:
//// Displays data in correct Format
TextReader textReader = new StreamReader("c:/users/tom/documents/visual studio 2010/Projects/DistanceCalculator3/DistanceCalculator3/TextFile1.txt");
var input = Convert.ToString(textReader.ReadToEnd());
var items = input.Split(',');
Console.WriteLine("Point Latitude Longtitude Elevation");
for (var i = 0; i < items.Length; i++)
{
if (i % 3 == 0)
{
Console.Write((i / 3) + "\t\t");
}
Console.Write(items[i]);
Console.Write("\t\t");
if (((i - 2) % 3) == 0)
{
Console.WriteLine();
}
}
Console.WriteLine();
Console.WriteLine();
//// Ask for two inputs from the user which is then converted into 6 floats and transferred in class Coordinates
Console.WriteLine("Please enter the two points that you wish to know the distance between:");
var point = Console.ReadLine();
string[] pointInput;
if (point != null)
{
pointInput = point.Split(' ');
}
else
{
goto RestartApplication;
}
var pointNumber = Convert.ToInt16(pointInput[0]);
var pointNumber2 = Convert.ToInt16(pointInput[1]);
var distance = new Coordinates
{
Latitude = Convert.ToDouble(items[pointNumber * 3]),
Longtitude = Convert.ToDouble(items[(pointNumber * 3) + 1]),
Elevation = Convert.ToDouble(items[(pointNumber * 3) + 2]),
Latitude2 = Convert.ToDouble(items[pointNumber2 * 3]),
Longtitude2 = Convert.ToDouble(items[(pointNumber2 * 3) + 1]),
Elevation2 = Convert.ToDouble(items[(pointNumber2 * 3) + 2])
};
//// Calculate the distance between two points
const double PIx = 3.141592653589793;
const double Radio = 6371;
var dlat = (distance.Latitude2 * (PIx / 180)) - (distance.Latitude * (PIx / 180));
var dlon = (distance.Longtitude2 * (PIx / 180)) - (distance.Longtitude * (PIx / 180));
var a = (Math.Sin(dlat / 2) * Math.Sin(dlat / 2)) + Math.Cos(distance.Latitude * (PIx / 180)) * Math.Cos(distance.Latitude2 * (PIx / 180)) * (Math.Sin(dlon / 2) * Math.Sin(dlon / 2));
var angle = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
var ultimateDistance = angle * Radio;
Console.WriteLine("The distance between your two points is...");
Console.WriteLine(ultimateDistance);
//// Repeat the program if the user enters 1, end the program if the user enters -1
Console.WriteLine("If you wish to calculate another distance type 1 and return, if you wish to end the program, type -1.");
var userInput = Console.ReadLine();
if (Convert.ToInt16(userInput) == 1)
{
//// Here is where the application will repeat.
goto RestartApplication;
}
}
also did a bit of code formatting. Hope it helps.
You could do that with goto, be aware however that this is considered bad practice.
static void Main(string[] args)
{
...
MyLabel:
...
if (Convert.ToInt16(Console.ReadLine()) == 1);
{
//here is where I need it to repeat
goto MyLabel;
}