这有点像覆盖 GetHashCode 的另一个答案,但我有不同的方法......因为公式似乎有一个字符串表示......
你不能覆盖 GetHashCode 并在覆盖中做一个
foreach(char c in ToString().ToCharArray()){
int hashCode |= c;
}
这样做的结果将产生一个 4 字节代码,它是等式中符号的打包表示......
如果每个符号都有可以在 HashTable 中查找的特定 OpCode,则可以采取进一步措施。
我会用每个 OpCode 的别名构建 HashTable,这样每个 Symbol 就不必声明属性 OpCode。
然后,我将在 Symbol 类上创建一个 Extension ToOpCode,该类在上述 HashTable 中进行查找。
然后我会在 GetHashCode 中使用 Extension 方法,例如
公式....
public override int GetHashCode(){
foreach(Symbol c in Symbols){
int hashCode |= c.ToOpCode();
}
}
象征....
public override int GetHashCode(){
retuurn Extensions.ToOpCode(this);
}
此实现将为 a + b 和 b + a 产生相同的哈希,这对于您的问题非常重要...
此外,如果您以正确的顺序指定 OpCode,您在技术上将能够以以下形式比较方程式:
(a) + (b)
==(a+b)
这可以通过确保括号操作码在哈希码中与数字不同的位置被赋予一个值来实现......
例如,如果您有 4 个字节(整数),则范围深度可以保留在第一个字节中,堆栈中上一个或下一个方程/符号的索引将是下一个,接下来的两个字节将保留用于符号数据和等式中的值/延续或变量数(不包括)。
这使您可以告诉某些事情,例如有多少嵌套级别等,因此您基本上也可以覆盖 Equals 以确保您可以区分a + b
andb + a
和(((a) + (b))
如果需要)。
例如,您可能想知道方程式是否与某种方法完全相同,但在另一种方法中,您可能想知道方程式是否在做同样的事情,但不是以完全相同的方式写成。
这也将允许您以不同的方式确定相等性,例如检查范围深度是否匹配以及等式中的步数是否完全相同,而不仅仅是基于哈希码假设。
例如,您可以按如下方式转换以确定以下内容:
hash << 8 将是 parens 的部门 hash << 16 将是堆栈的上一个或下一个等式指针 hash << 24 将是等式中的符号或代码值延续或变量数(不包括)
你也可以只做 hash == anotherHash 但是这种方式给你更多的灵活性,几乎没有开销。
如果您在 Hash 中需要更多空间,则创建一个返回 long 的新方法 GetExtendedHashCode,然后在 GetHashCode 中移位/向下转换或重新格式化 ExtendedHashCode 以匹配 CLR 所需的 int 格式。
您还可以获得符号能够以这种方式表示变量和值的好处,方法是将它们留在堆栈上并像 CLR 一样使用它们。