5

如何强制加倍 x = 3 / 2; 在没有 D 后缀或强制转换的情况下返回 1.5 in x?是否有任何类型的运算符重载可以完成?还是一些编译器选项?

令人惊讶的是,添加强制转换或后缀并不是那么简单,原因如下:

业务用户需要编写和调试自己的公式。目前 C# 正在像 DSL(领域特定语言)一样被使用,因为这些用户不是计算机科学工程师。所以他们所知道的就是如何编辑和创建几种类型的类来保存他们的“业务规则”,这些规则通常只是数学公式。

但他们总是假设 double x = 3 / 2; 将返回 x = 1.5,但在 C# 中返回 1。

A. 他们总是忘记这一点,浪费时间调试,打电话给我寻求支持,我们修复它。B. 他们认为这很丑陋并且损害了他们业务规则的可读性。

如您所知,DSL 需要更像自然语言。

是的。我们正计划迁移到 Boo 并基于它构建一个 DSL,但那是在路上。

是否有一个简单的解决方案可以使 double x = 3 / 2; 通过类外部的东西返回 1.5 所以它对用户不可见?

谢谢!韦恩

4

9 回答 9

5

不,没有可以使3 / 2回报 1.5 的解决方案。

考虑到您的约束的唯一解决方法是阻止用户在公式中使用文字。鼓励他们使用常量。或者,如果他们真的需要使用文字,鼓励他们使用带小数点的文字。

于 2010-03-21T04:18:44.133 回答
1

永远不要说永远......(双)3/2 解决方案看起来不错......

但它失败了 4+5/6

试试这个:捐赠给公共领域,供 SymbolicComputation.com 自由使用。
它是 alpha 版,但您可以尝试一下,我只在几个测试中运行过它,我的网站和软件应该很快就会上线。它使用微软的 Roslyn,如果一切顺利,它会在每个数字后加上一个“d”。Roslyn 也是 alpha,但它会解析相当多的 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();
    }
于 2012-03-27T20:53:02.533 回答
0

很简单,如果我没记错的话:

double x = 3D / 2D;
于 2010-03-21T04:15:53.043 回答
0

一种解决方案是编写一种方法来为他们执行此操作并教他们使用它。您的方法将始终采用双精度数,并且答案将始终具有正确的小数位数。

于 2010-03-21T04:26:40.257 回答
0

我不太确定,但我相信你可以使用 3.0/2.0 获得双倍但是如果你认为 .0 只是作为后缀的另一种方式,那么它也不是答案:-)

于 2010-03-21T04:33:12.107 回答
0

也许您现在可以尝试RPN 表达式解析器类bcParser?这些是非常小的表达式解析库。

我喜欢在我自己的工作中使用强大的静态类型语言,但我认为它们不适合对成为专业人士不感兴趣的初学者。

所以我不得不说不幸的是,你选择的 C# 可能不是最适合那些观众的。

Boo 似乎是静态输入的。您是否考虑过嵌入 Javascript 引擎、Python 或其他一些动态类型引擎?这些通常并不难插入现有应用程序,并且您可以从大量现有文档中受益。

于 2010-03-21T04:39:01.100 回答
0

也许是 int32 上的扩展方法?

于 2010-03-21T14:23:05.437 回答
0

在将公式传递给 c# 编译器之前对其进行预处理。执行以下操作:

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

将整数文字转换为双精度文字。

或者,您可以使用简单的状态机来跟踪您是否在字符串文字或注释中,而不是盲目地替换,但对于简单的公式,我认为正则表达式就足够了。

于 2010-03-21T19:09:51.483 回答
0

尝试这样做:

double result = (double) 3 / 2;

结果 = 1.5

于 2010-04-13T12:43:27.493 回答