2010-03-21 6 views
5

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

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

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

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

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

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

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

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

Спасибо! Wayne

+7

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

ответ

5

Нет, нет никакого решения, которое может сделать 3/2 возвращение 1.5.

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

+1

Ну, кроме решений, которые делают. –

+0

@jdk, вроде? ... – Anzurio

+0

как решение http://stackoverflow.com/questions/2485881/how-to-force-c-binary-int-division-to-return-a-double/2485892#2485892 .. и, как вы упомянули но я, вероятно, прокомментировал после первого предложения или до того, как вы закончили. Так что никаких разногласий в контексте в конце концов. –

0

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

double x = 3D/2D; 
+0

Вопросник говорит: без суффикса D или литья – Anzurio

0

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

0

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

+0

Это предположение, а не ответ. Ответьте на вопросы, которые входят в ваш опыт. Неправильные ответы затрудняют поиск полезных советов. –

0

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

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

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

Boo, кажется, статически типизирован. Думали ли вы о внедрении движка Javascript, Python или какого-либо другого динамически типизированного движка? Как правило, это не так сложно подключить к существующему приложению, и у вас есть много документов.

+0

Python перед версией 3.0 имеет ту же проблему с делением. – dan04

+0

Ну, пользователи все любят C#, потому что их первоочередной задачей является производительность. И критический код пути системы был написан в небезопасном использовании указателя, поэтому, говорят они, это самое быстрое программное обеспечение в торговой индустрии. Поэтому они до сих пор довольствуются C#, пока мы не сможем создать полный DSL. – Wayne

+0

FYI, поскольку выбор языка, кажется, Boo - это ответ, поскольку он является расширяемым.То есть вы можете изменить что-либо в дереве парсеров на любом этапе процесса компиляции. Моя единственная проблема заключается в том, что функции отладчика различаются по важности и автоматическое завершение кода, которые доступны с C#. Я еще не уверен, что происходит с возможностью перехода через код для бизнес-пользователей, если он находится на модифицированном языке Boo. – Wayne

0

Возможно, метод extenstion для int32?

+0

Я бы ЛЮБЛЮ это как решение и исследовал его конкретно и даже пробовал. Но, по-видимому, вы не можете создать оператор над загрузчиками в качестве методов расширения в соответствии с авторами языка C#. Если я ошибаюсь, пожалуйста, поправьте меня. – Wayne

0

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

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

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

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

+0

Очень умный. «Формулы» - действительно полные методы с условными и вспомогательными методами. Это довольно сложная логика поверх формул. В частности, это автоматизированные торговые правила. – Wayne

0

Попробуйте сделать это следующим образом:

double result = (double) 3/2; 

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

1

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

но это не удалось для 4 + 5/6

попробуйте следующее: пожертвовано общественному достоянию, которое будет использоваться свободно на SymbolicComput.com.
Это альфа, но вы можете попробовать, я только запускаю его на нескольких тестах, мой сайт и программное обеспечение должны скоро появиться. Он использует Microsoft Roslyn, он поместит «d» после каждого номера, если все будет хорошо. Рослин тоже альфа, но он будет разбирать честный бит 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(); 
    }