Как заставить c # бинарное деление int вернуть двойной? - PullRequest
5 голосов
/ 21 марта 2010

Как заставить двойной х = 3/2; вернуть 1,5 в x без суффикса D или приведения? Есть ли какая-либо перегрузка оператора, которая может быть сделана? Или какой-то вариант компилятора?

Удивительно, но добавить кастинг или суффикс не так просто по следующей причине:

Бизнес-пользователи должны писать и отлаживать свои собственные формулы. В настоящее время C # используется как DSL (предметно-ориентированный язык), поскольку эти пользователи не являются инженерами в области компьютерных наук. Поэтому все, что они знают, это как редактировать и создавать несколько типов классов для хранения их «бизнес-правил», которые обычно являются просто математическими формулами.

Но они всегда предполагают, что double x = 3/2; вернет х = 1,5 однако в C # возвращается 1.

A. они всегда об этом забывают, тратят время на отладку, зовут меня на поддержку и мы исправляем. Б. они думают, что это очень некрасиво и вредит читабельности их бизнес-правил.

Как вы знаете, DSL должен быть больше похож на естественный язык.

Да. Мы планируем перейти на Boo и построить DSL на его основе, но это еще не все.

Есть ли простое решение сделать двойной х = 3/2; вернуть 1.5 чем-то внешним для класса, чтобы оно было невидимым для пользователей?

Спасибо! Wayne

Ответы [ 9 ]

5 голосов
/ 21 марта 2010

Нет, нет решения, которое может заставить 3 / 2 вернуть 1,5.

Единственный обходной путь, учитывающий ваши ограничения, - это не рекомендовать пользователям использовать литералы в формуле. Поощряйте их использовать константы. Или, если им действительно нужно использовать литералы, рекомендуйте им использовать литералы с десятичной точкой.

1 голос
/ 28 марта 2012

никогда не говори никогда ... (Двойное) решение 3/2 выглядит неплохо ...

, но оно не удалось в течение 4 + 5/6

попробуйте это: пожертвовано публикеДомен для свободного использования SymbolicComputation.com.
Это альфа-версия, но вы можете попробовать ее, я запускаю ее только на нескольких тестах, мой сайт и программное обеспечение должны скоро появиться.Он использует Roslyn от Microsoft, он будет ставить 'd' после каждого числа, если все пойдет хорошо.Roslyn тоже альфа-версия, но она разберет немного 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();
    }
0 голосов
/ 13 апреля 2010

Попробуйте сделать это так:

double result = (double) 3 / 2;

результат = 1,5

0 голосов
/ 21 марта 2010

Предварительная обработка формул перед передачей их компилятору c #. Сделайте что-то вроде:

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

Чтобы преобразовать целочисленные литералы в двойные литералы.

В качестве альтернативы, вы можете использовать простой конечный автомат для отслеживания того, используете ли вы строковый литерал или комментарий, а не заменять их вслепую, но для простых формул я думаю, что регулярного выражения будет достаточно.

0 голосов
/ 21 марта 2010

Возможно, метод расширения на int32?

0 голосов
/ 21 марта 2010

Может быть, вы можете попробовать Класс анализатора выражений RPN на данный момент или bcParser ?Это очень маленькие библиотеки разбора выражений.

Мне нравятся сильные, статически типизированные языки для моей собственной работы, но я не думаю, что они подходят для начинающих, которые не заинтересованы в том, чтобы стать профессионалами.скажем, к сожалению, ваш выбор C # не мог бы быть лучшим для этой аудитории.

Похоже, что Boo типично статически.Задумывались ли вы о встраивании движка Javascript, Python или другого движка с динамической типизацией?Как правило, их не так сложно подключить к существующему приложению, и вы можете использовать множество существующей документации.

0 голосов
/ 21 марта 2010

Я не совсем уверен, но я верю, что вы можете получить двойной, используя 3.0 / 2.0 Но если вы думаете .0 просто как другой способ суффикса, то это тоже не ответ: -)

0 голосов
/ 21 марта 2010

Одним из решений будет написание метода, который сделает это для них, и научит их использовать его. Ваш метод всегда будет принимать двойные числа, а ответ всегда будет иметь правильное количество десятичных знаков.

0 голосов
/ 21 марта 2010

просто, если я не ошибаюсь:

double x = 3D / 2D;
...