Link to home
Start Free TrialLog in
Avatar of perrytaylor
perrytaylor

asked on

Order of Operations for custom operators

At my request some of the experts came up w/ a class that replicated a double data type except it has an operator ^ that replaces math.pow().  This works wonderfully except that in long calculations it executes at the same order as + or -.  Is there a way to set the order of operations of a custom operator so that the power will execute before the multiplication or addition?
public struct Double
    {
        public double value;
 
        public Double(double d)
        {
            value = d;
        }
 
        public Double(Double D)
        {
            value = D.value;
        }
 
        public static double operator ^(Double A, Double B)
        {
            Double C = new Double();
            C = Math.Pow(A.value, B.value);
            return C;
        }
 
        public static double operator ^(Double A, double B)
        {
            Double C = new Double(); 
            C= Math.Pow(A.value, B);
            return C;
        }
 
        public static double operator ^(Double A, int B)
        {
            return Math.Pow(A.value, B);
        }
 
        public static double operator ^(double A, Double B)
        {
            return Math.Pow(A, B.value);
        }
 
        public static implicit operator Double(double d)
        {
            return fromdouble(d);
        }
 
        public static implicit operator double(Double D)
        {
            return fromDouble(D);
        }
 
        public static double fromDouble(Double D)
        {
            return D.value;
        }
 
        public static Double fromdouble(double d)
        {
            return new Double(d);
        }
    }

Open in new window

Avatar of kaufmed
kaufmed
Flag of United States of America image

As abel stated, there isn't a way to alter operator precedence without using parentheses. For your reference, the order of operations in c# can be found here:

http://msdn.microsoft.com/en-us/library/6a71f45d.aspx
ASKER CERTIFIED SOLUTION
Avatar of abel
abel
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
In light of my last comment, the only suitable override that I can think of is actually the index operator. Which cannot be overloaded, but there's a "trick" which you can use: indexers, to achieve the same goal.

But would that be a good thing to do? Redefining ^ is one thing (because it is little used, there's not too much danger to say that "what used to be a logical or, is now a power operator"), but saying that [] means power is another.

Consider this:

// current
Double d1, d2, d3;
Double result = d1 ^ (d2 ^ d3);   // without the bracket it would evaluate (d1 ^ d2) ^ d3
 
//or the only alternative I can think of:
Double d1, d2, d3;
Double result = d1[d2[d3]];      // no extra brackets needed, but is it clearer?

Open in new window

Ah, forgot to add the reference to my quotes, apologies: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf
Avatar of perrytaylor
perrytaylor

ASKER

I guess this begs the question then what should I do for a couple of equations that are over 5,000 characters long w/ about 500 ^ in them?  Is there any way to get around manually going in there and putting Math.Pow() in place of ^?
Yes, you can, of course. What about using something totally off-limits: the Data objects have a DataTable (iirc, I can be amiss on the names) that have a Calculate method which takes a string that contains simple operators to act on a datafield.

If you need performance, we need to do it slightly different though. I can help you with a regular expression to do the replace on your math expr.

And on yet another streak it is possible to create a simple parser yourself that does the Math.Pow and/or the other mathematical expressions for you. I believe there are already such expression validators available in .NET. Enough to warrant a new question? ;-)
I actually figured out a completely different workaround that is turning out to be ideal.  A little bit of background, the functions are kinematic calculations that were originally devised using maple.  I don't have a seat of maple right now, but I do have symbolic toolbox in MATLAB.  Using the ccode() function I can take the matlab code and generate C code that is optimized (i.e. the function is broken down into subfunctions theoretically should run faster).  I haven't proofed it yet, but it seems to do the trick.
That sounds like a much more viable option to me! Now you only need to learn to "talk" to a C/C++ file, if you need to access this from VB/C#.
the ccode() command in matlab produces a text file that is compatible w/ C.  All I need to do is copy it into my C# project and run a find replace for things like pow( to Math.Pow( and it's done.  thanks for all your help, you've taught me a ton.