Printing Calculation result - c#

I'm trying to write a print function that would help me with printing the results of the addition, subtraction, etc.
I've tried to do this in a switch - case statement, but it doesn't seems to be working.
Is there any easier ways to implement this print() function?
Secondly, in case of exception, how can I manage exceptions if for instance one of the operations throw an exception. such as 3/0!
for this program I have a Calculator class and a Program, where all this will be tested.
public class Calculator
{
public double Add(double x, double y)
{
return x + y;
}
public double Subtract(double x, double y)
{
return x - y;
}
public double Multiply(double x, double y)
{
return x * y;
}
public double Power(double x, double y)
{
return Math.Pow(x, y);
}
public void PrintCalculation(string action)
{
switch (action)
{
case "Add":
Console.WriteLine("Sum is: {0}", Add(x, y));
break;
case "Subtract":
Console.WriteLine("Division is: {0}", Subtract(x, y));
break;
case "Multiply":
Console.WriteLine("Multiply is: {0}", Multiply(x, y);
break;
case "Power":
Console.WriteLine("Power is: {0}", Power(x, y);
break;
}
}
}
This is the Main function
namespace MyCalculator
{
public class Program : Calculator
{
static void Main()
{
Calculator myCal = new Calculator();
myCal.Add(2, 3);
myCal.Subtract(3, 3);
myCal.Multiply(5, 5);
myCal.Power(2, 3);
myCal.PrintCalculation("Add");
myCal.PrintCalculation("Subtract");
myCal.PrintCalculation("Multiply");
}
}
}

A few issues, first of all you are not passing strings into PrintCalculation(string s). The format should be something like:
PrintCalculation("Add");
As the function is currently defined. Also in PrintCalculation() you call your calculation functions which are then passed undefined values of x and y. They are not members of the class or the class method itself.
For example you are trying to call Add(x,y) inside of PrintCalculation("Add"), but you never give it an x or y in that function. Instead the function should be defined
public void PrintCalculation(string action, double x, double y){
// code here
}
And it should be called with
PrintCalculation("Add", 2, 3);

There are a few problems with the code that are causing compiler errors, such as missing parenthesis, quotes, and break statements. But I think the main issue is that you're not taking in the values of x and y to your PrintCalculation method, so they are undefined in the body of that method.
To fix this, you can just add them to the argument list as you have with the other methods:
public static void PrintCalculation(string action, double x , double y)
But notice that you're doing a string comparison here, which can be prone to errors due to case sensitivity (what happens if they write "add" instead of "Add"?). A different option might be to create an enum to represent valid actions. This also serves to restrict the input allowed to only values we can do something with (previously the user may have tried to enter "Divide", and been confused when nothing happened):
public enum Action { Add, Subtract, Multiply, Power }
Then your method could be changed to accommodate the enum instead of a string. We can also make the class and methods static, since there is no state required:
public static class Calculator
{
public enum Action { Add, Subtract, Multiply, Power }
public static double Add(double x, double y)
{
return x + y;
}
public static double Subtract(double x, double y)
{
return x - y;
}
public static double Multiply(double x, double y)
{
return x * y;
}
public static double Power(double x, double y)
{
return Math.Pow(x, y);
}
public static void PrintCalculation(Action action, double x , double y)
{
switch (action)
{
case Action.Add:
Console.WriteLine("The sum of {0} and {1} is: {2}",
x, y, Add(x, y));
break;
case Action.Subtract:
Console.WriteLine("The difference between {0} and {1} is: {2}",
x, y, Subtract(x, y));
break;
case Action.Multiply:
Console.WriteLine("The product of {0} and {1} is: {2}",
x, y, Multiply(x, y));
break;
case Action.Power:
Console.WriteLine("{0} raised to the power of {1} is: {2}",
x, y, Power(x, y));
break;
}
}
}
With these changes, we can now use the class like:
private static void Main(string[] cmdArgs)
{
var first = 7;
var second = 3;
Calculator.PrintCalculation(Calculator.Action.Add, first, second);
Calculator.PrintCalculation(Calculator.Action.Subtract, first, second);
Calculator.PrintCalculation(Calculator.Action.Multiply, first, second);
Calculator.PrintCalculation(Calculator.Action.Power, first, second);
GetKeyFromUser("\nDone! Press any key to exit...");
}
Output

I think you can take advantage of logging the actions without requiring a switch case at all. The example below allows you to set an Action<string> for logging the results dynamically.
public class Calculator
{
public Action<string> LogAction { get; set;}
private double PerformCalculation(string calculationName, string format, double x, double y, Func<double, double, double> calcFunction)
{
double value = calcFunction(x, y);
LogAction?.Invoke(string.Format(format, x, y, value));
return calcFunction(x, y);
}
public double Add(double x, double y)
{
string format = "The sum of {0} and {1} is: {2}";
return PerformCalculation("Add", format, x, y, (a, b) => a + b);
}
public double Subtract(double x, double y)
{
string format = "The difference between {0} and {1} is: {2}";
return PerformCalculation("Subtract", format, x, y, (a, b) => a - b);
}
public double Multiply(double x, double y)
{
string format = "The product of {0} and {1} is: {2}";
return PerformCalculation("Multiply", format, x, y, (a, b) => a * b);
}
public double Power(double x, double y)
{
string format = "{0} raised to the power of {1} is: {2}";
return PerformCalculation("Power", format, x, y, (a, b) => Math.Pow(a, b));
}
}
static void Main(string[] args)
{
Calculator myCal = new Calculator();
myCal.LogAction = Console.WriteLine; // Sets all calculation output to the console.
myCal.Add(2, 3);
myCal.Subtract(3, 3);
myCal.Multiply(5, 5);
myCal.Power(2, 3);
Console.ReadLine();
}

Your problemn is: you start the method to do something
Main:
myCal.Add(2, 3);
Class:
public double Add(double x, double y)
{
return x + y;
}
but you don't store the outcome anywhere. You see, the method knows to return something, but on the other end is nothing to receive it like
double i = myCal.Add(2, 3);
or, as an alternative you can store your numbers in the class
public double _outcome;
public void Add(double x, double y)
{
_outcome = x + y;
}
and in main
myCal.PrintCalculation(myCal._outcome.ToString());
As an alternative (to do it the way you actually want it to)
Main:
myCal.TmpNumberOne = 1;
myCal.TmpNumberTwo = 2;
myCal.PrintCalculation("Add");
Class:
public double TmpNumberOne;
public double TmpNumberTwo;
public double Add(double x, double y)
{
return x + y;
}
public void PrintCalculation(string action)
{
switch (action)
{
case "Add":
Console.WriteLine("Sum is: {0}", Add(TmpNumberOne, TmpNumberTwo).ToString());
break;
}
}
To your final question: you want exceptionhandling, first you coudl achieve this by adding an if-statement to your method to check for invalid inputs, or you take the holy
try
{
}
catch(Exception ex)
{
}
you can paste your code inside try, when an error would occur that stops the program entirely, the code in catch code is executed instead. If you are fancy you can print out the exception with
ex.ToString();
don't forget to convert your double values to string, otherwise this will throw an error

Related

Chain asynchronous operations that return Either using Language-Ext in C#

I am using the Language-Ext library for C# and I am trying to chain asynchronous operations that return an Either type. Let's say that I have three functions that would return an integer if they succeed and a string if the fail, and another function that sums the result of the previous three functions. In the sample implementations below Op3 fails and returns a string.
public static async Task<Either<string, int>> Op1()
{
return await Task.FromResult(1);
}
public static async Task<Either<string, int>> Op2()
{
return await Task.FromResult(2);
}
public static async Task<Either<string, int>> Op3()
{
return await Task.FromResult("error");
}
public static async Task<Either<string, int>> Calculate(int x, int y, int z)
{
return await Task.FromResult(x + y + z);
}
I want to chain these operations and I am trying to do it like this:
var res = await (from x in Op1()
from y in Op2()
from z in Op3()
from w in Calculate(x, y, z)
select w);
But we the code does not compile because I get the error cannot convert from 'LanguageExt.Either<string, int>' to 'int' for the arguments of Calculate. How should I chain these functions?
The problem is that the LINQ query can't work out which version of SelectMany to use, because x isn't used in the second line. You can get around this by converting your Task<Either<L, R>> to EitherAsync<L, R>:
public static async Task<int> M()
{
var res = from x in Op1().ToAsync()
from y in Op2().ToAsync()
from z in Op3().ToAsync()
from w in Calculate(x, y, z).ToAsync()
select w;
return await res.IfLeft(0);
}
Or, instead of returning Task<Either<L, R>> return EitherAsync<L, R>:
public static EitherAsync<string, int> Op1() =>
1;
public static EitherAsync<string, int> Op2() =>
2;
public static EitherAsync<string, int> Op3() =>
3;
public static EitherAsync<string, int> Calculate(int x, int y, int z) =>
x + y + z;
public static async Task<int> M()
{
var res = from x in Op1()
from y in Op2()
from z in Op3()
from w in Calculate(x, y, z)
select w;
return await res.IfLeft(0);
}
x, y and z are not of type int, but of Either<string, int> change Calculate(int x, int y, int z) to accept instances of Either calls: Calculate(Either<string, int> x, Either<string, int> y, Either<string, int>z), or pass
x.{The int getter property}

My delegate type isn't working "Method name expected"

I tried this:
class Program
{
public delegate int add(int x, int y);
public class ff
{
public static int addNumbers(int x, int y)
{
return x + y;
}
public static int substractNumbers(int x, int y)
{
return x - y;
}
static void Main(string[] args)
{
Delegate delegare = new add(ff.addNumbers);
Console.WriteLine(delegare(3,4));
}
}
I don't see why I'm getting this error"Method name expected".
When I use a delegate with a void function it works.
Can someone help me?
The type of your delegare variable is just Delegate. That could refer to any delegate. In order to invoke a delegate (in the normal way), you should have an expression of the appropriate type.
After fixing the naming conventions and removing the unnecessary nested class - and demonstrating a method group conversion - your code looks like this:
using System;
public delegate int Int32Operation(int x, int y);
class Program
{
public static int AddNumbers(int x, int y)
{
return x + y;
}
public static int SubtractNumbers(int x, int y)
{
return x - y;
}
static void Main(string[] args)
{
Int32Operation op = new Int32Operation(AddNumbers);
Console.WriteLine(op(3, 4)); // Prints 7
op = SubtractNumbers; // Method group conversion
Console.WriteLine(op(3, 4)); // Prints -1
}
}
You should try this out:
add delegare = new add(ff.addNumbers);
The type of your delegate should be add since you defined so.

How to access Interface method implemented in the derived class from child class?

I have two interfaces A,B both has same method declarations. I have a class C inheriting from interfaces A,B. I have another class D inheriting from C. Now i want to access the implemented methods in C from D
interface A
{
int add(int x, int y);
int mul(int x, int y);
}
interface B
{
int add(int x, int y);
int mul(int x, int y);
}
public class C : A,B
{
int A.add(int x,int y)
{
return x + y;
}
int A.mul(int x,int y)
{
return 0;
}
int B.add(int x, int y)
{
return x;
}
int B.mul(int x, int y)
{
return y;
}
}
class D : C
{
}
How to access the methods in C from D?
How to access the methods in C from D?
You have to use a reference with a compile-time of the relevant interface. For example:
class D
{
public void FooA()
{
A a = this;
Console.WriteLine(a.mul(...));
}
public void FooB()
{
B b = this;
Console.WriteLine(b.mul(...));
}
}
Of course you don't need the local variable - you can cast:
Console.WriteLine(((A) this).mul(...));
... but it gets a bit ugly.
This is just because you're using explicit interface implementation. If you implemented one of the interfaces implicitly, you could just call the methods directly as normal... but explicit interface implementation only allows a member to be called via that interface.
An explicit interface method invocation should always work
((A)this).mul(1,1);
You can use this code because you have to specify the interface from which you want to use the method (A or B):
((A)this).add(1, 1);
As others already suggested casting is of course one way of doing this. It's quick and simple but if you're going to use it a lot it's annoying. The way out in this case are properties that give access to the members provided by the interface and that conveniently group them thus simplifying their usage:
Easy access without additional casting (you do it only once inside the property getters - see below the C-class):
class Program
{
static void Main(string[] args)
{
C c = new C();
c.As.add(1, 2);
}
}
Interfaces:
public interface A
{
int add(int x, int y);
int mul(int x, int y);
}
public interface B
{
int add(int x, int y);
int mul(int x, int y);
}
C-class:
public class C : A, B
{
// Methods from the A-interface.
public A As { get { return (A)this; } }
// Methods from the B-interface.
public B Bs { get { return (B)this; } }
int A.add(int x, int y)
{
return x + y;
}
int A.mul(int x, int y)
{
return 0;
}
int B.add(int x, int y)
{
return x;
}
int B.mul(int x, int y)
{
return y;
}
}
D-class:
public class D : C
{
public D()
{
base.As.add(1, 2);
base.Bs.add(3, 4);
}
}
Can you check this,
using System;
public class Program
{
public static void Main()
{
D ds=new D(10,12);
int valueAddtion=((A)ds).add(20,122);
int valueMultiplication=((B)ds).mul(20,11);
Console.WriteLine("Mainapplicatin Value of A= " +valueAddtion+" multiplication value= "+valueMultiplication);
}
}
// your code segment here
class D : C
{
public D()
{
int valueAdd=((A)this).add(10,11);
int valueMul=((B)this).mul(20,11);
Console.WriteLine("Addition Value of A= " +valueAdd+" multiplication value= "+valueMul);
}
public D(int x,int y):this()
{
int valueAdd=((A)this).add(x,y);
int valueMul=((B)this).mul(x,y);
Console.WriteLine("Paremeterized Value of A= " +valueAdd+" multiplication value= "+valueMul);
}
}
Output will be,
Addition Value of A= 21 multiplication value= 11
Paremeterized Value of A= 22 multiplication value= 12
Mainapplicatin Value of A= 142 multiplication value= 11

Fix my Graphics vector class, One of the parameters of a binary operator must be the containing type

http://codepaste.net/i87t39
The error I get is "One of the parameters of a binary operator must be the containing type"
public class Vector3D<T>
{
public T x;
public T y;
public T z;
public Vector3D()
{
}
public Vector3D(T a, T b, T c)
{
x = a; y = b; z = c;
}
/*public Vector3D(double a, double b, double c)
{
x = a; y = b; z = c;
}*/
public override string ToString()
{
//return base.ToString();
return String.Format("({0} {1} {2})", x , y , z);
}
public Vector3D<double> operator+( Vector3D<double> right)
{
Vector3D<double> vd = new Vector3D<double>() { x = 0, y = 0, z = 0};
vd.x = left.x + right.x;
vd.y = left.y + right.y;
vd.z = left.z + right.z;
return vd;
}
}
If I copy the code in your link:
public class Vector3D<T>
{
public T x;
public T y;
public T z;
public Vector3D()
{
}
public Vector3D(T a, T b, T c)
{
x = a; y = b; z = c;
}
public override string ToString()
{
//return base.ToString();
return String.Format("({0} {1} {2})", x , y , z);
}
public Vector3D<double> operator+( Vector3D<double> right)
{
Vector3D<double> vd = new Vector3D<double>() { x = 0, y = 0, z = 0};
vd.x = left.x + right.x;
vd.y = left.y + right.y;
vd.z = left.z + right.z;
return vd;
}
}
The error which you have is in operator+, because the containing type is Exp<T>, not Exp<double>. You should change it. Also there is no definition of left in this method !
Your method should like something like that:
public static Vector3D<T> operator +(Vector3D<T> right)
{
Vector3D<T> vd = new Vector3D<T>();
vd.x = right.x;
vd.y = right.y;
vd.z = right.z;
return vd;
}
Without a lot of extra work, you're not going to be able to implement a fully general-purpose generic Vector3D<T> class complete with mathematical operators. There are no constraints that you can provide for the generic type that will at once allow T to be a built-in numeric type and at the same time provide math operators for T.
There are a variety of ways to deal with this, such as special-casing the type in the generic class (yuck!), requiring T to implement an interface (i.e. wrap a normal numeric type in a type that implements the interface), or making the type abstract and requiring specialized subclasses to implement the operators as named methods (one of which could even depend on an interface, while others based directly on numeric types would just implement them directly).
For example:
abstract class Vector3D<T>
{
public readonly T x;
public readonly T y;
public readonly T z;
public Vector3D() { }
public Vector3D(T x, T y, T z)
{
this.x = x;
this.y = y;
this.z = z;
}
public abstract Vector3D<T> Add(Vector3D<T> right);
}
class Vector3DDouble : Vector3D<double>
{
public Vector3DDouble() { }
public Vector3DDouble(double x, double y, double z)
: base(x, y, z)
{ }
public override Vector3D<double> Add(Vector3D<double> right)
{
return new Vector3DDouble(x + right.x, y + right.y, z + right.z);
}
}
Assuming for the moment you've somehow addressed that issue, let's look at your operator + overload. First, your code won't even compile. You have overloaded the unary + operator, because you only have one parameter right for the overload, but in the method body you assume a second parameter left which is undeclared.
A more sensible implementation might look like this:
public static Vector3D<T> operator+(Vector3D<T> left, Vector3D<T> right)
{
return left.Add(right);
}
Note: I'm assuming here you've solved the arithmetic issue by requiring implementers to provide the arithmetic operations via named method, e.g. Add() per my example above. Obviously the exact implementation here would depend on how you dealt with the general issue of doing math with T values.

C# - Passing Delegate as a parameter to a method

I am trying to get familiar with the concept of delegates in C#. I have created this console application so far:
Program.cs
using System;
namespace DelegatesTest
{
class Program
{
static void Main(string[] args)
{
ArithmeticOperation.ArOpDel additionDelegate = new ArithmeticOperation.ArOpDel(ArithmeticOperation.Addition);
Console.WriteLine(ArithmeticOperation.ConvertResultToString(additionDelegate(10, 5)));
Console.ReadKey();
}
}
}
ArithmeticOperation.cs
using System;
namespace DelegatesTest
{
public static class ArithmeticOperation
{
public delegate int ArOpDel(int x, int y);
public static string ConvertResultToString(ArOpDel del)
{
string result = String.Format("The result of the {0} operation is {1}", del.Method.Name, del.ToString());
return result;
}
public static int Addition(int x, int y)
{
return x + y;
}
public static int Subtraction(int x, int y)
{
return x - y;
}
public static int Multiplication(int x, int y)
{
return x * y;
}
public static int Division(int x, int y)
{
return x / y;
}
}
}
As you can see from the code, I am using a static class called ArithmeticOperation.cs to perform some arithmetic operations. The ConvertResultToString method takes one of the arithmetic operations methods as a parameter in order to display the result elegantly as a string.
Unfortunately, my code does not compile. It is giving me the following error:
Argument '1': cannot convert from 'int' to 'DelegatesTest.ArithmeticOperation.ArOpDel'
The error is being given on this line:
Console.WriteLine(ArithmeticOperation.ConvertResultToString(additionDelegate(10, 5)));
Can you please help me solve this problem as I am not very experienced with delegates? In fact, I have created this application to learn about delegates.
The additionDelegate(10, 5) will return int by doing arithmetic operation, it will not return deleagate that's the reason of compilation error.
Console.WriteLine(ArithmeticOperation.ConvertResultToString(additionDelegate(10, 5)));
You are not passing the delegate here. You are calling it, which results in an int.
This would pass the delegate:
Console.WriteLine(ArithmeticOperation.ConvertResultToString(additionDelegate));
You would need to actually call the delegate somewhere though.
when you do this
Console.WriteLine(ArithmeticOperation.ConvertResultToString(additionDelegate(10, 5)));
you are forcing the compiler to execute the method and return the result to pass it as an argument which in this case it's an int while the ConvertResultTostring expect a delegate
here how you can get it work without using generic
class Program
{
static void Main(string[] args)
{
ArithmeticOperation.ArOpDel additionDelegate = ArithmeticOperation.Addition;
Console.WriteLine(ArithmeticOperation.ConvertResultToString(additionDelegate,5,6));
Console.ReadKey();
}
}
public static class ArithmeticOperation
{
public delegate int ArOpDel(int x, int y);
public static string ConvertResultToString(ArOpDel del,int x, int y )
{
string result = String.Format("The result of the {0} operation is {1}", del.Method.Name, del(x,y).ToString());
return result;
}
public static int Addition(int x, int y)
{
return x + y;
}
public static int Subtraction(int x, int y)
{
return x - y;
}
public static int Multiplication(int x, int y)
{
return x * y;
}
public static int Division(int x, int y)
{
return x / y;
}
}
additionDelegate(10, 5) is an invocation of additionDelegate which actually is an Addition function. So, the result is an integer.
In order to pass a delegate you should pass additionDelegate itself instead of additionDelegate(10, 5). But, in this case, the result of the operation will not be available in ConvertResultToString unless you invoke it there.
public static string ConvertResultToString(ArOpDel del)
{
string result = String.Format("The result of the {0} operation is {1}", del.Method.Name, del(10, 5).ToString());
return result;
}
...
Console.WriteLine(ArithmeticOperation.ConvertResultToString(additionDelegate));
additionDelegate(10, 5) means invoke the delegate,the result is an int type which does not match the ConvertResultToString method stub.
you need change
Console.WriteLine(ArithmeticOperation.ConvertResultToString(additionDelegate(10, 5)))
to
Console.WriteLine(ArithmeticOperation.ConvertResultToString(additionDelegate))
and change
string result = String.Format("The result of the {0} operation is {1}", del.Method.Name, del.ToString());
to
string result = String.Format("The result of the {0} operation is {1}", del.Method.Name, del(10,5).ToString());

Categories