0

I am creating a calculator like project which requires performing operations +, -, *, /, %, ^ on variables. Standard operations are of type var1 OP var2. I have the type of both the variables at runtime, which can either be Int64 or double.

I can convert both of them to double and perform calculations, but I'd rather prefer doing integer-based calculations when both variables are integers (otherwise convert both to double). This is what I have got so far (for addition)


if (container1.vType == Interop.variableType.DOUBLE || container2.vType == Interop.variableType.DOUBLE)
    return Convert.ToDouble(container1.value) + Convert.ToDouble(container2.value);
return (Int64)container1.value + (Int64)container2.value;

However, due to multiple operations, using same/similar code over and over will create unnecessary redundancy (I'll simply have to change the operator).

So how should I do this so that it has both high performance and minimal/no redundancy?

Grimson
  • 540
  • 1
  • 5
  • 21
  • What is the compile time type of container1.values and container2.values? – Vikhram Sep 27 '16 at 03:23
  • what unnecessary redundancy are you having? Also, what do you expect to be in container1.value and container2.value? Are they string? int64? double? Convert.ToDouble is used to convert string to double. While (Int64) is just casting. If your value is string, then you might need to use Convert. But, if the value is either int or double, then you can just cast it. – kurakura88 Sep 27 '16 at 07:06
  • container1.value and container2.value are basically objects which container either a int or a double. And therefore if one is int and other is double, I convert them to doubles. And if none are double, I type cast them to ints and do operations. By redundancy, I meant writing similar code for each case. Similar stuff would be written for -, *, / etc. i.e. those 3 lines for EACH of the case. Any way I can get around that? – Grimson Sep 27 '16 at 07:42

1 Answers1

2

This is another way of doing it. It reduces your code duplication, but increases the LOC. It is for sure less efficient than invoking the operator directly. The main benefit of doing it this way is scalability and modularity for long term maintenance.

class Evaluator {
    Dictionary<string, Func<dynamic, dynamic, dynamic>> BinaryOperatorsDyn = new Dictionary<string, Func<dynamic, dynamic, dynamic>>();

    public Evaluator() {
        LoadOperators();
    }

    void LoadOperators() {
        BinaryOperatorsDyn.Add("+", (x, y) => x + y);
        BinaryOperatorsDyn.Add("-", (x, y) => x - y);
        BinaryOperatorsDyn.Add("*", (x, y) => x * y);
    }

    public void DoDemo() {
        long x = 20;
        double y = 30;
        var oper = "+";

        var result = BinaryOperatorsDyn[oper](x, y);
        Console.WriteLine($"Result of {x} + {y} is {result}. Type of result is {result.GetType().ToString()}");
    }
}
class Program {
    static void Main(string[] args) {
        var eval = new Evaluator();
        eval.DoDemo();
    }
}
Vikhram
  • 4,294
  • 1
  • 20
  • 32
  • I like the solution, but aren't dynamics very expensive to use? – Grimson Sep 27 '16 at 13:18
  • They are more expensive than using static types. How much more depends on the situation. Check [this post](http://stackoverflow.com/a/7480977/5671993) for details – Vikhram Sep 27 '16 at 18:39