Func<int, int> 的数学等式
Mathematical Equality for Func<int, int>
我有一个 Sequence
类型实现了 ISequence
。 ISequence
实现 IEnumerable<Element>
其中 Element
是另一种自定义类型。目前,我的 Sequence
类型将生成序列的第 N 项的指令存储为 Func<int, int>
。这很方便,因为它允许我通过对 Func
的简单调用来调用 NTerm(int n)
,并使用 lambda 创建 Sequence
。我想避免改变这种方法。
我想根据两个 Func
的相等性来检查两个 Sequence 对象的相等性。我开始四处浏览,有几个 posts 使用 Expression
s 分解 lambdas 和 Func
s 用于相等,但我说的是数学相等。
In other words, x => 2 * x
should equal c => c * 2
, along with any variations of mathematical expressions, such as Math.Pow or more involved operators. If I can get that to work, I can compare Sequence
s for mathematical equality.
我尝试编写自己的扩展方法:
public static bool MathEquals(this Expression<Func<int, int>> f,
Expression<Func<int, int>> g)
我不确定如何从那里开始。我写了一些基本的默认值:
if (ReferenceEquals (f, g)) return true;
if (f == null || g == null) return false;
if (f.NodeType != g.NodeType || f.Type != g.Type) return false;
但我需要检查两个 lambda 表达式的数学相等性,即两个 Func<int, int>
。这可以做到吗?有没有人有办法解决吗?我是否需要更改存储第 N 项公式的方法?我反对检查输出,因为某些输出的序列可能相等,但并非全部。
如果我需要 post 任何序列代码,我会的。
更新: 我决定将斯科特的回答标记为已接受。然而,这项工作还没有完成。查看第二部分 here.
您的问题分为两部分,"How do I break apart a expression and evaulate it" 和 "How do I check that two expressions mean the same logical operation"。
我不知道第二部分怎么做,但我知道第一部分。
您需要做的是通过覆盖 VisitBinary
并构建所有操作的列表来创建 ExpressionVisitor
and have it walk through each BinaryExpression
。
public class OperationParser : ExpressionVisitor
{
public OperationParser()
{
Expressions = new List<BinaryExpression>();
}
public List<BinaryExpression> Expressions { get; private set; }
protected override Expression VisitBinary(BinaryExpression b)
{
Expressions.Add(b);
return base.VisitBinary(b);
}
}
那你会做
Expression<Func<int, int>> expression1 = (x) => x + 2;
Expression<Func<int, int>> expression2 = (y) => 2 + y;
var parser1 = new OperationParser();
parser1.Visit(expression1);
var parser2 = new OperationParser();
parser2.Visit(expression2);
//TODO: write a way to compare parser1.Expressions to parser2.Expressions to see if they "mean the same thig"
您只需要在TODO中填写"your second question"
我有一个 Sequence
类型实现了 ISequence
。 ISequence
实现 IEnumerable<Element>
其中 Element
是另一种自定义类型。目前,我的 Sequence
类型将生成序列的第 N 项的指令存储为 Func<int, int>
。这很方便,因为它允许我通过对 Func
的简单调用来调用 NTerm(int n)
,并使用 lambda 创建 Sequence
。我想避免改变这种方法。
我想根据两个 Func
的相等性来检查两个 Sequence 对象的相等性。我开始四处浏览,有几个 posts 使用 Expression
s 分解 lambdas 和 Func
s 用于相等,但我说的是数学相等。
In other words,
x => 2 * x
should equalc => c * 2
, along with any variations of mathematical expressions, such as Math.Pow or more involved operators. If I can get that to work, I can compareSequence
s for mathematical equality.
我尝试编写自己的扩展方法:
public static bool MathEquals(this Expression<Func<int, int>> f,
Expression<Func<int, int>> g)
我不确定如何从那里开始。我写了一些基本的默认值:
if (ReferenceEquals (f, g)) return true;
if (f == null || g == null) return false;
if (f.NodeType != g.NodeType || f.Type != g.Type) return false;
但我需要检查两个 lambda 表达式的数学相等性,即两个 Func<int, int>
。这可以做到吗?有没有人有办法解决吗?我是否需要更改存储第 N 项公式的方法?我反对检查输出,因为某些输出的序列可能相等,但并非全部。
如果我需要 post 任何序列代码,我会的。
更新: 我决定将斯科特的回答标记为已接受。然而,这项工作还没有完成。查看第二部分 here.
您的问题分为两部分,"How do I break apart a expression and evaulate it" 和 "How do I check that two expressions mean the same logical operation"。
我不知道第二部分怎么做,但我知道第一部分。
您需要做的是通过覆盖 VisitBinary
并构建所有操作的列表来创建 ExpressionVisitor
and have it walk through each BinaryExpression
。
public class OperationParser : ExpressionVisitor
{
public OperationParser()
{
Expressions = new List<BinaryExpression>();
}
public List<BinaryExpression> Expressions { get; private set; }
protected override Expression VisitBinary(BinaryExpression b)
{
Expressions.Add(b);
return base.VisitBinary(b);
}
}
那你会做
Expression<Func<int, int>> expression1 = (x) => x + 2;
Expression<Func<int, int>> expression2 = (y) => 2 + y;
var parser1 = new OperationParser();
parser1.Visit(expression1);
var parser2 = new OperationParser();
parser2.Visit(expression2);
//TODO: write a way to compare parser1.Expressions to parser2.Expressions to see if they "mean the same thig"
您只需要在TODO中填写"your second question"