开发者

How to force c# binary int division to return a double?

How to force double x = 3 / 2; to return 1.5 in x without the D suffix or casting? Is there any kind of operator overload tha开发者_运维百科t can be done? Or some compiler option?

Amazingly, it's not so simple to add the casting or suffix for the following reason:

Business users need to write and debug their own formulas. Presently C# is getting used like a DSL (domain specific language) in that these users aren't computer science engineers. So all they know is how to edit and create a few types of classes to hold their "business rules" which are generally just math formulas.

But they always assume that double x = 3 / 2; will return x = 1.5 however in C# that returns 1.

A. they always forget this, waste time debugging, call me for support and we fix it. B. they think it's very ugly and hurts the readability of their business rules.

As you know, DSL's need to be more like natural language.

Yes. We are planning to move to Boo and build a DSL based on it but that's down the road.

Is there a simple solution to make double x = 3 / 2; return 1.5 by something external to the class so it's invisible to the users?

Thanks! Wayne


No, there's no solution that can make 3 / 2 return 1.5.

The only workaround taking into consideration your constraints is to discourage the users to use literals in the formula. Encourage them to use constants. Or, if they really need to use literals, Encourage them to use literals with a decimal point.


never say never... The (double)3/2 solution looks nice...

but it failed for 4+5/6

try this: donated to the public domain to be used freely by SymbolicComputation.com.
It's alpha but you can try it out, I've only run it on a few tests, my site and software should be up soon. It uses Microsoft's Roslyn, it'll put a 'd' after every number if all goes well. Roslyn is alpha too, but it will parse a fair bit of C#.

    public static String AddDSuffixesToEquation(String inEquation)
    {
        SyntaxNode syntaxNode = EquationToSyntaxNode(inEquation);
        List<SyntaxNode> branches = syntaxNode.DescendentNodesAndSelf().ToList();
        List<Int32> numericBranchIndexes = new List<int>();
        List<SyntaxNode> replacements = new List<SyntaxNode>();
        SyntaxNode replacement;
        String lStr;
        Int32 L;
        for (L = 0; L < branches.Count; L++)
        {
            if (branches[L].Kind == SyntaxKind.NumericLiteralExpression)
            {
                numericBranchIndexes.Add(L);
                lStr = branches[L].ToString() + "d";
                replacement = EquationToSyntaxNode(lStr);
                replacements.Add(replacement);
            }
        }

        replacement = EquationToSyntaxNode(inEquation);
        List<SyntaxNode> replaceMeBranches;
        for (L = numericBranchIndexes.Count - 1; L >= 0; L--)
        {
            replaceMeBranches = replacement.DescendentNodesAndSelf().ToList();
            replacement = replacement.ReplaceNode(replaceMeBranches[numericBranchIndexes[L]],replacements[L]);
        }
        return replacement.ToString();

    }

    public static SyntaxNode EquationToSyntaxNode(String inEquation)
    {
        SyntaxTree tree = EquationToSyntaxTree(inEquation);
        return EquationSyntaxTreeToEquationSyntaxNode(tree);
    }

    public static SyntaxTree EquationToSyntaxTree(String inEquation)
    {
        return SyntaxTree.ParseCompilationUnit("using System; class Calc { public static object Eval() { return " + inEquation + "; } }");
    }

    public static SyntaxNode EquationSyntaxTreeToEquationSyntaxNode(SyntaxTree syntaxTree)
    {
        SyntaxNode syntaxNode = syntaxTree.Root.DescendentNodes().First(x => x.Kind == SyntaxKind.ReturnStatement);
        return syntaxNode.ChildNodes().First();
    }


simple, if I'm not mistaken:

double x = 3D / 2D;


One solution would be writing a method that does this for them and teach them to use it. Your method would always take in doubles and the answer will always have the correct number of decimals.


I'm not pretty sure, but I believe you can get a double using 3.0/2.0 But if you think .0 just as another way of suffixing then it's not the answer too :-)


Maybe you can try RPN Expression Parser Class for now or bcParser? These are very small expression parsing libraries.

I like strong, statically typed languages for my own work, but I don't think they're suited for beginners who have no interest in becoming professionals.

So I'd have to say unfortunately your choice of C# might not of been the best for that audience.

Boo seems to be statically typed to. Have you thought about embedding a Javascript engine, Python, or some other dynamically typed engine? These usually are not that hard to plug into an existing application and you have the benefit of lots of existing documentation.


Perhaps an extenstion method on int32?


Preprocess formulas before passing them to the c# compiler. Do something like:

formula = Regex.Replace(formula, @"(^|[\^\s\+\*\/-])(\d+)(?![DF\.])", "$1$2D")

To convert integer literals to double literals.

Alternately, you could use a simple state machine to track whether or not you're in a string literal or comment rather than blindly replacing, but for simple formulas I think a regex will suffice.


Try doing it like this:

double result = (double) 3 / 2;

result = 1.5

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜