Having trouble with C# quadratic equation solver - c#

I just wrote my first C# program.
It's a simple piece of code which solves quadratic equations.
It works with some functions (such as -6x2-6x+12) perfectly, while with others, (4x2-20x+25) it exhibits what I suspect are rounding errors.
I'm completely new to C#, and I can't see an problems; would someone be able to help me debug this code?
namespace ConsoleApplication {
class Program {
static int ObtainInput(string prompt, bool canBeZero) {
double a = ObtainInput("A? ", false);
double b = ObtainInput("B? ", true);
double c = ObtainInput("C? ", true);
double d, x1, x2;
while (true) {
Console.Write(prompt);
string input = Console.ReadLine();
int result;
bool success = int.TryParse(input, out result);
if (success && (canBeZero || result != 0))
return result;
Console.WriteLine("Invalid input!");
}
// Calculating a discriminant
d = b * b - 4 * a * c;
if (d == 0) {
x1 = -b / (2 * a);
Console.WriteLine("The only solution is x={0}.", x1);
Console.ReadLine();
}
// If d < 0, no real solutions exist
else if (d < 0) {
Console.WriteLine("There are no real solutions");
Console.ReadLine();
}
// If d > 0, there are two real solutions
else {
x1 = (-b - Math.Sqrt(d)) / (2 * a);
x2 = (-b + Math.Sqrt(d)) / (2 * a);
Console.WriteLine("x1={0} and x2={1}.", x1, x2);
Console.ReadLine();
}
}
}
}

I just wrote my first C# program.
Awesome. Now would be a great time to not get into bad habits:
entA: Console.Write("a?");
try { a = Convert.ToInt32(Console.ReadLine()); }
catch
{ /*If a=0, the equation isn't quadratic*/
Console.WriteLine("Invalid input");
goto entA;
}
Problems abound. First off, use int.TryParse, rather than putting a try-catch around something that can fail.
Second, the comment does not match the action of the code. The code determines if the result is an integer; the comment says that it checks for zero.
Third, do not use a goto when what you are attempting to represent is a loop.
Fourth, look at all that duplicated code! You have the same code repeated three times with minor variations.
Make yourself a helper method:
static int ObtainInput(string prompt, bool canBeZero)
{
while(true) // loop forever!
{
Console.Write(prompt);
string input = Console.ReadLine();
int result;
bool success = int.TryParse(input, out result);
if (success && (canBeZero || result != 0))
return result;
Console.WriteLine("Invalid input!");
}
}
And now your mainline is:
int a = ObtainInput("A? ", false);
int b = ObtainInput("B? ", true);
int c = ObtainInput("C? ", true);
Your bug though is here:
x1 = x2 = -b / (2 * a);
You do the arithmetic in integers, and then convert to doubles. That is, you do the division, round to the nearest integer, and then convert to double. Do it in doubles (or, less likely, in decimals) from the start. It should be:
double a = ObtainInput("A? ", false);
double b = ObtainInput("B? ", true);
double c = ObtainInput("C? ", true);
That is, a, b, and c should not ever be integers.

You're doing integer division when assigning to x1 and x2; (you can just change the 2 to 2.0 to change it to double division and get a double result)
It might also make sense to change your a,b,c, and d values to double which will also get past the problem, and allow people to enter non-int values for the coefficients.

int a, b, c;
int d;
first of all, try to use double instead of int, since 1/3 = 0 using integers.

Related

Is it possible to reduce repetitive permutation-based if-statements?

Hello I'm working on this math game and for my last scene I did what feels like a lot of repetitive code but I'm not sure if there's a way to simplify it, I have linked below so maybe some more seasoned programmers might have some more elegant solutions!
For example, Im trying to generate every permutation of something like (a[]b)²[]c[]d where the brackets will be replaced by +,-,*, or /. What I have been doing is just creating random percent if statements to pick a specific version like "(a+b)²/c-d" Is there possibly a less "brute-force" and readable approach then what I have been doing?
if(UnityEngine.Random.Range(0,101)>50){
// 50% of being (a+b)²(c)+d
if(UnityEngine.Random.Range(0,101)>50){
ans = ((int) Mathf.Pow((float) a+ (float) b, 2))*c+d;
input.text = "("+a+"+"+b+")"+"²"+"("+c+")"+"+"+d+"=";
Debug.Log("Problem ID: 78");
// 50% of being (a+b)²(c)-d
} else {
ans = ((int) Mathf.Pow((float) a+ (float) b, 2))*c-d;
input.text = "("+a+"+"+b+")"+"²"+"("+c+")"+"-"+d+"=";
Debug.Log("Problem ID: 79");
}
// 50% of being (a-b)²(c)[]d
} else {
// 50% of being (a-b)²(c)+d
if(UnityEngine.Random.Range(0,101)>50){
ans = ((int) Mathf.Pow((float) a- (float) b, 2))*c+d;
input.text = "("+a+"-"+b+")"+"²"+"("+c+")"+"+"+d+"=";
Debug.Log("Problem ID: 80");
// 50% of being (a-b)²(c)-d
} else {
ans = ((int) Mathf.Pow((float) a- (float) b, 2))*c-d;
input.text = "("+a+"-"+b+")"+"²"+"("+c+")"+"-"+d+"=";
Debug.Log("Problem ID: 81");
}
(Pastebin below for more context)
https://pastebin.pl/view/d1bfb99e
I applaud your desire to make your code more readable. The basic idea is to split (a) defining, (b) choosing and (c) applying your operators.
Step 1: You define Operators. Each Operator combines both a mathematical operation (e.g. Add would be (a, b) => a + b) and a symbol (e.g. Add would be "+").
class Operator
{
public Func<int, int, int> Calculate { get; }
public string Symbol { get; }
public Operator(Func<int, int, int> calculate, string symbol)
{
Calculate = calculate;
Symbol = symbol;
}
}
private Operator Add = new Operator((a, b) => (a + b), "+");
private Operator Subtract = new Operator((a, b) => (a - b), "-");
Step 2: Then you randomly choose your operators (I used System.Random, since I'm not familiar with Unity, but feel free to replace it with the random number generator of your choice):
var rnd = new Random();
private (Operator op1, Operator op2, int problemId) RandomlyChooseProblem()
{
switch (rnd.Next(4))
{
case 0: return (Add, Add, 78);
case 1: return (Add, Subtract, 79);
case 2: return (Subtract, Add, 80);
case 3: return (Subtract, Subtract, 81);
default: throw new InvalidOperationException("This should not happen.");
}
}
Step 3: You apply them:
var (op1, op2, problemId) = RandomlyChooseProblem();
ans = op2.Calculate((int)Math.Pow(op1.Calculate(a, b), 2) * c, d);
input.text = $"(a{op1.Symbol}b)²*c{op2.Symbol}d");
Debug.Log($"Problem ID: {problemId}");
Adding a new operator (e.g. Multiply) or a new problem variant (e.g. (Add, Multiply, 82)) is now just a single line of code.
Break the calculation into parts - a±b, square * c and ±d. Calculate them separately, and multiply them to get the final result. For the text, you can use string interpolation
float ans;
string operator1;
string operator2;
if (UnityEngine.Random.Range(0,101)>50) {
ans = (float) a + (float) b;
operator1 = "+";
} else {
ans = (float) a - (float) b;
operator1 = "-";
}
ans = (int)(ans * ans) * c;
if (UnityEngine.Random.Range(0,101)>50) {
ans += d;
operator2 = "+";
} else {
ans -= d;
operator2 = "-";
}
input.text = $"(a{operator1}b)²(c){operator2}d";
Also note that UnityEngine.Random.Range(0,101) > 50 is not exactly 50% probability. You probably meant UnityEngine.Random.Range(1,101) > 50 instead, but I would just use UnityEngine.Random.Range(0,2) == 0.
The problem IDs can be flattened by generating 2 random bits, and adding the 2-bit number encoded by those bits to 78:
float ans;
string operator1;
string operator2;
int random1 = UnityEngine.Random.Range(0,2);
int random2 = UnityEngine.Random.Range(0,2);
if (random1 == 0) {
ans = (float) a + (float) b;
operator1 = "+";
} else {
ans = (float) a - (float) b;
operator1 = "-";
}
ans = (int)(ans * ans) * c;
if (random2 == 0) {
ans += d;
operator2 = "+";
} else {
ans -= d;
operator2 = "-";
}
int problemID = 78 + random1 + random2 * 2;
Debug.Log($"Problem ID: {problemID}");
input.text = $"(a{operator1}b)²(c){operator2}d";
This trick is not particularly readable IMO though.

How to show solutions for quadratic formula

So I wrote a Quadratic formula program in C#, how do I take the quadratic formula program and modify it so that the program correctly displays the number of solutions.
if there are two solutions,
(x - x1)(x - x2) = 0
if there is only one solution,
(x - x0)^2 = 0
if there are no solutions,
No Solution.
This is the program, if someone could show the solution to this for me that would be wonderful, I'm really stuck on how to do it.
using System;
namespace quadraticequation
{
class MainClass
{
public static void Main(string[] args)
{
Console.WriteLine("Enter a number for a"); //ask the user for information
double a = double.Parse(Console.ReadLine()); //Gets a from the user
Console.WriteLine("Enter a number for b"); //asks the user for information
double b = double.Parse(Console.ReadLine()); //Gets b from the user
Console.WriteLine("Enter a number for c"); //asks the user for information
double c = double.Parse(Console.ReadLine()); //Gets c from the user
//double.Parse --> is used to convert a number or string to a double.
//Console.ReadLine() --> is used to take the input from the user.
//We call a function here
Quadratic(a, b, c);
}
//We need to create a new function
public static void Quadratic(double a, double b, double c)
{
double deltaRoot = Math.Sqrt(b * b - 4 * a * c); //Math.Sqrt takes the square root of the number
if (deltaRoot >= 0) // we use an if statement here to handle information
{
double x1 = (-b + deltaRoot) / 2 * a; //We write the information for x1 here
double x2 = (-b - deltaRoot) / 2 * a; //We write the information for x2 here
Console.WriteLine("x1 = " + x1 + " x2 = " + x2); //we use this to write the roots
}
else // we use an else statement so that we dont return an error when there are no roots
{
Console.WriteLine("There are no roots");
}
}
}
}
I think you have to review your second degree formula solution-skills. You write:
double deltaRoot = Math.Sqrt(b * b - 4 * a * c);
But the test is actually whether b2-4×a×c is larger than or equal to zero: indeed that is actually why we check it: because we cannot take the square root of a negative number (yeah there exist complex numbers that can take the square root of a negative number, but let's ignore that for now).
So the solution is to write it like:
public static void Quadratic(double a, double b, double c) {
double delta = b*b-4*a*c; //only delta
if (delta > 0) {
double deltaRoot = Math.Sqrt(delta);
double x1 = (-b + deltaRoot) / (2 * a); //We write the information for x1 here
double x2 = (-b - deltaRoot) / (2 * a); //We write the information for x2 here
Console.WriteLine("x1 = " + x1 + " x2 = " + x2); //we use this to write the roots
} else if(delta == 0) {
double x1 = -b/(2*a);
Console.WriteLine("x1 = " + x1); //we use this to write the roots
} else {
Console.WriteLine("There are no roots");
}
}
You also have to write (-b + deltaRoot) / (2*a) (with (2*a)), otherwise you will multiply (-b + deltaRoot) / 2 with a instead.
A final note is that equality comparisons with floating points is very tricky so delta == 0 will often fail since the result can be something 1e-20-ish, which is simply an error when performing floating point arithmetic. So it is perhaps better to use a small range of values.
This gives:
csharp> MainClass.Quadratic(1,1,1);
There are no roots
csharp> MainClass.Quadratic(1,1,0);
x1 = 0 x2 = -1
csharp> MainClass.Quadratic(1,0,0);
x1 = 0

How should I compare these doubles to get the desired result?

I have a simple example application here where I am multiplying and adding double variables and then comparing them against an expected result. In both cases the result is equal to the expected result yet when I do the comparison it fails.
static void Main(string[] args)
{
double a = 98.1;
double b = 107.7;
double c = 92.5;
double d = 96.5;
double expectedResult = 88.5;
double result1 = (1*2*a) + (-1*1*b);
double result2 = (1*2*c) + (-1*1*d);
Console.WriteLine(String.Format("2x{0} - {1} = {2}\nEqual to 88.5? {3}\n", a, b, result1, expectedResult == result1));
Console.WriteLine(String.Format("2x{0} - {1} = {2}\nEqual to 88.5? {3}\n", c, d, result2, expectedResult == result2));
Console.Read();
}
And here is the output:
2x98.1 - 107.7 = 88.5
Equal to 88.5? False
2x92.5 - 96.5 = 88.5
Equal to 88.5? True
I need to be able to capture that it is in fact True in BOTH cases. How would I do it?
Floating point numbers often don't contain the exact value that mathematics tells us, because of how they store numbers.
To still have a reliable comparison, you need to allow some difference:
private const double DoubleEpsilon = 2.22044604925031E-16;
/// <summary>Determines whether <paramref name="value1"/> is very close to <paramref name="value2"/>.</summary>
/// <param name="value1">The value1.</param>
/// <param name="value2">The value2.</param>
/// <returns><c>true</c> if <paramref name="value1"/> is very close to value2; otherwise, <c>false</c>.</returns>
public static bool IsVeryCloseTo(this double value1, double value2)
{
if (value1 == value2)
return true;
var tolerance = (Math.Abs(value1) + Math.Abs(value2)) * DoubleEpsilon;
var difference = value1 - value2;
return -tolerance < difference && tolerance > difference;
}
Please also make sure to read this blog post.
If you need more precision (for money and such) then use decimal.
var a = 98.1M;
var b = 107.7M;
var c = 92.5M;
var d = 96.5M;
var expectedResult = 88.5M;
var result1 = (2 * a) + (-1 * b);
var result2 = (2 * c) + (-1 * d);
Console.WriteLine(String.Format("2x{0} - {1} = {2}\nEqual to 88.5? {3}\n", a, b, result1, expectedResult == result1));
Console.WriteLine(String.Format("2x{0} - {1} = {2}\nEqual to 88.5? {3}\n", c, d, result2, expectedResult == result2));
Output:
2x98.1 - 107.7 = 88.5
Equal to 88.5? True
2x92.5 - 96.5 = 88.5
Equal to 88.5? True
It's a problem with how floating point numbers are represented in memory.
You should read this to get a better understanding of whats going on: What Every Computer Scientist Should Know About Floating-Point Arithmetic
Simply change your rounding to level 2 , this will give TRUE
double result1 =Math.Round ( (1 * 2 * a) + (-1 * 1 * b),2);
using Math.Round() will round result1 to the correct decimal
result1 = Math.Round(result1, 1);
using the debugger,
result1=88.499999999999986;
expectedResult = 88.5
So when using the double ,these are not equal.
There is a whole school of thought that is against using Double.Epsilon and similar numbers...
I think they use this: (taken from https://stackoverflow.com/a/2411661/613130 but modified with the checks for IsNaN and IsInfinity suggested here by nobugz
public static bool AboutEqual(double x, double y)
{
if (double.IsNaN(x)) return double.IsNaN(y);
if (double.IsInfinity(x)) return double.IsInfinity(y) && Math.Sign(x) == Math.Sign(y);
double epsilon = Math.Max(Math.Abs(x), Math.Abs(y)) * 1E-15;
return Math.Abs(x - y) <= epsilon;
}
The 1E-15 "magic number" is based on the fact that doubles have a little more than 15 digits of precision.
I'll add that for your numbers it returns true :-)

How do I round doubles in human-friendly manner in C#?

In my C# program I have a double obtained from some computation and its value is something like 0,13999 or 0,0079996 but this value has to be presented to a human so it's better displayed as 0,14 or 0,008 respectively.
So I need to round the value, but have no idea to which precision - I just need to "throw away those noise digits".
How could I do that in my code?
To clarify - I need to round the double values to a precision that is unknown at compile time - this needs to be determined at runtime. What would be a good heuristic to achieve this?
You seem to want to output a value which is not very different to the input value, so try increasing numbers of digits until a given error is achieved:
static double Round(double input, double errorDesired)
{
if (input == 0.0)
return 0.0;
for (int decimals = 0; decimals < 17; ++decimals)
{
var output = Math.Round(input, decimals);
var errorAchieved = Math.Abs((output - input) / input);
if (errorAchieved <= errorDesired)
return output;
}
return input;
}
}
static void Main(string[] args)
{
foreach (var input in new[] { 0.13999, 0.0079996, 0.12345 })
{
Console.WriteLine("{0} -> {1} (.1%)", input, Round(input, 0.001));
Console.WriteLine("{0} -> {1} (1%)", input, Round(input, 0.01));
Console.WriteLine("{0} -> {1} (10%)", input, Round(input, 0.1));
}
}
private double PrettyRound(double inp)
{
string d = inp.ToString();
d = d.Remove(0,d.IndexOf(',') + 1);
int decRound = 1;
bool onStartZeroes = true;
for (int c = 1; c < d.Length; c++ )
{
if (!onStartZeroes && d[c] == d[c - 1])
break;
else
decRound++;
if (d[c] != '0')
onStartZeroes = false;
}
inp = Math.Round(inp, decRound);
return inp;
}
Test:
double d1 = 0.13999; //no zeroes
double d2 = 0.0079996; //zeroes
double d3 = 0.00700956; //zeroes within decimal
Response.Write(d1 + "<br/>" + d2 + "<br/>" + d3 + "<br/><br/>");
d1 = PrettyRound(d1);
d2 = PrettyRound(d2);
d3 = PrettyRound(d3);
Response.Write(d1 + "<br/>" + d2 + "<br/>" + d3 +"<br/><br/>");
Prints:
0,13999
0,0079996
0,00700956
0,14
0,008
0,007
Rounds your numbers as you wrote in your example..
I can think of a solution though it isn't very efficient...
My assumption is that you can tell when a number is in the "best" human readable format when extra digits make no difference to how it is rounded.
eg in the example of 0,13999 rounding it to various numbers of decimal places gives:
0
0.1
0.14
0.14
0.14
0.13999
I'd suggest that you could loop through and detect that stable patch and cut off there.
This method seems to do this:
public double CustomRound(double d)
{
double currentRound = 0;
int stability = 0;
int roundLevel = 0;
while (stability < 3)
{
roundLevel++;
double current = Math.Round(d, roundLevel);
if (current == currentRound)
{
stability++;
}
else
{
stability = 1;
currentRound=current;
}
}
return Math.Round(d, roundLevel);
}
This code might be cleanable but it does the job and is a sufficient proof of concept. :)
I should emphasise that that initial assumption (that no change when rounding) is the criteria we are looking at which means that something like 0.3333333333 will not get rounded at all. With the examples given I'm unable to say if this is correct or not but I assume if this is a double issues that the problem is with the very slight variations from the "right" value and the value as a double.
Heres what I tried:
public decimal myRounding(decimal number)
{
double log10 = Math.Log10((double) number);
int precision = (int)(log10 >= 0 ? 0 : Math.Abs(log10)) + (number < 0.01m ? 1 : 2);
return Math.Round(number, precision);
}
test:
Console.WriteLine(myRounding(0.0000019999m)); //0.000002
Console.WriteLine(myRounding(0.0003019999m)); //0.0003
Console.WriteLine(myRounding(2.56777777m)); //2.57
Console.WriteLine(myRounding(0.13999m)); //0.14
Console.WriteLine(myRounding(0.0079996m)); //0.008
You can do it without converting to string. This is what I created fast:
private static double RoundDecimal(double number)
{
double temp2 = number;
int temp, counter = 0;
do
{
temp2 = 10 * temp2;
temp = (int)temp2;
counter++;
} while (temp < 1);
return Math.Round(number, counter < 2 ? 2 : counter);
}
or
private static double RoundDecimal(double number)
{
int counter = 0;
if (number > 0) {
counter = Math.Abs((int) Math.Log10(number)) + 1;
return Math.Round(arv, counter < 2 ? 2 : counter);
}
After giving it another thought I did the following and looks like it does what I want so far.
I iterate over the number of digits and compare Round( value, number ) and Round( value, number + 1 ). Once they are equal (not == of course - I compare the difference against a small number) then number is the number of digits I'm looking for.
Double.ToString() can take a string format as an argument. This will display as many characters as you require, rounding to the decimal place. E.G:
double Value = 1054.32179;
MessageBox.Show(Value.ToString("0.000"));
Will display "1054.322".
Source
Generic formats (i.e, pre-generated)
How to generate custom formats
You can use no of digits with Math.Round Function
Double doubleValue = 4.052102;
Math.Round(doubleValue, 2);
This will return 4.05 as your required answer.
This is tested code, can u explain me how i am wrong. So i need to change.

C# How to determine if a number is a multiple of another?

Without using string manipulation (checking for an occurrence of the . or , character) by casting the product of an int calculation to string.
and
without using try / catch scenarios relying on errors from data types.
How do you specifically check using C# if a number is a multiple of another?
For example 6 is a multiple of 3, but 7 is not.
Try
public bool IsDivisible(int x, int n)
{
return (x % n) == 0;
}
The modulus operator % returns the remainder after dividing x by n which will always be 0 if x is divisible by n.
For more information, see the % operator on MSDN.
bool isMultiple = a % b == 0;
This will be true if a is a multiple of b
Use the modulus (%) operator:
6 % 3 == 0
7 % 3 == 1
I don't get that part about the string stuff, but why don't you use the modulo operator (%) to check if a number is dividable by another? If a number is dividable by another, the other is automatically a multiple of that number.
It goes like that:
int a = 10; int b = 5;
// is a a multiple of b
if ( a % b == 0 ) ....
I tried to solve this problem using the modulus operator (%), but it did not work. What worked for me was (12 is an example, it can be any number, i is an integer number):
double v1 = i / 12.0;
int v2 = i / 12;
double dif = v1 - v2;
bool boolDif = false;
if (dif==0.0)
{
boolDif = true;
//more code here
}
Here is what we do in the case of having doubles to compare.
E.g. value == 1.2d and baseValue == 0.1d shall give true and 1.2d and 0.5d shall give false:
public static bool IsMultipleOf(double value, double baseValue)
{
var d = value / baseValue;
return Math.Abs(d - Math.Round(d, MidpointRounding.AwayFromZero)) <= 1E-05;
}
followings programs will execute,"one number is multiple of another" in
#include<stdio.h>
int main
{
int a,b;
printf("enter any two number\n");
scanf("%d%d",&a,&b);
if (a%b==0)
printf("this is multiple number");
else if (b%a==0);
printf("this is multiple number");
else
printf("this is not multiple number");
return 0;
}
there are some syntax errors to your program heres a working code;
#include<stdio.h>
int main()
{
int a,b;
printf("enter any two number\n");
scanf("%d%d",&a,&b);
if (a%b==0){
printf("this is multiple number");
}
else if (b%a==0){
printf("this is multiple number");
}
else{
printf("this is not multiple number");
return 0;
}
}

Categories