按位运算符递归
Recursion with bitwise operators
我在 java
中有以下使用递归简化 Nor expressions
的方法:
public Expression simplify() {
// x ↓ T = F
if (this.getRight().toString().equals("T")) {
return new Val(false).simplify();
}
// T ↓ x = F
if (this.getLeft().toString().equals("T")) {
return new Val(false).simplify();
}
// x ↓ F = ~(x)
if (this.getRight().toString().equals("F")) {
return new Not(super.getLeft().simplify());
}
// F ↓ x = ~(x)
if (this.getLeft().toString().equals("F")) {
return new Not(super.getRight().simplify());
}
// x ↓ x = ~(x)
if (this.getLeft().toString().equals(this.getRight().toString())) {
return new Not(this.getRight().simplify());
}
return new Nor(this.getLeft().simplify(), this.getRight().simplify());
}
现在,当我想简化表达式 (T ↓ y) ↓ y
时,它会输出 F ↓ y
而不是 ~(y)
.
我需要如何更改递归以输出正确的简化表达式?
你的情况没有被涵盖,所以你得到默认值,一直到最后:简化左边,简化右边,然后 return 那。
问题是,您简化了左侧节点,将 (T ↓ y)
变为 F
,右侧节点(没有变化),但是您无法继续应用简化:您只是 return lhs ↓ rhs
, 不简化这个.
一个非常简单的调试运行应该已经找到了,不是吗?也许下次尝试阅读您的代码并在达到 SO 之前多逐步执行它。
就其价值而言,我将在此处进行 2 项重大改进:
我会从里到外工作,这几乎从定义上讲更聪明,因为您的简化规则都只适用于非复杂节点。
因此,我会采用您的左右节点,首先简化它们,然后 运行 您的简化规则。这样就无需简化最终结果。
因此,不要在一百万个地方传递 super.getRight()
,而是从:
开始
Node left = getLeft().simplify();
Node right = getRight().simplify();
然后检查你的规则,这次只使用左和右(与 super.getLeft().simplify()
相比)。如果你的规则中的 none 适用,则进一步的简化不会帮助你,所以你可以 return new Nor(left, right)
,然后就可以完成了。
第二个主要更新:toString()
是一个调试/日志工具 仅 - 与 toString 相比,对业务逻辑进行编程必然会破坏行为,即使它不是直接错误。因此,通过 getLeft().toString().equals("T")
检查 'is the left node the node representing a constant TRUE value' 是糟糕的代码风格,并且会自找麻烦。
应该有一个正确的方法来检查这个。可能是 if (left.isConstantTrue())
或者 if (left.equals(Node.TRUE))
,或者可能是 if (left instanceof Constant c && c.value)
(这是 JDK16 语法,没有 JDK16 就很啰嗦:if ((left instanceof Constant) && ((Constant) left).value)
.
None 其中依赖于调试辅助代码永远不会更改,并且任何其他节点也永远不会打印 T
,并且通常将您的代码修复为惯用的,而不是一个会触发所有 linter 工具的东西。
此外,super
调用很奇怪。您有时调用 super.getRIght
,有时调用 this.getRight
。通常,除非有特定原因,否则不要指定 this/super。为什么要跳过 getRight
的任何本地覆盖?您可能没有/您甚至可能 没有 覆盖,这使得 super.getRight()
、this.getRight()
和 getRight()
都 100% 等效。只需写 getRight()
- 与您的语义意图相匹配,即 'get the Right node',而不是 'get the superclass impl of getRight, intentionally skipping past any custom modifications this instance has performed'.
我在 java
中有以下使用递归简化 Nor expressions
的方法:
public Expression simplify() {
// x ↓ T = F
if (this.getRight().toString().equals("T")) {
return new Val(false).simplify();
}
// T ↓ x = F
if (this.getLeft().toString().equals("T")) {
return new Val(false).simplify();
}
// x ↓ F = ~(x)
if (this.getRight().toString().equals("F")) {
return new Not(super.getLeft().simplify());
}
// F ↓ x = ~(x)
if (this.getLeft().toString().equals("F")) {
return new Not(super.getRight().simplify());
}
// x ↓ x = ~(x)
if (this.getLeft().toString().equals(this.getRight().toString())) {
return new Not(this.getRight().simplify());
}
return new Nor(this.getLeft().simplify(), this.getRight().simplify());
}
现在,当我想简化表达式 (T ↓ y) ↓ y
时,它会输出 F ↓ y
而不是 ~(y)
.
我需要如何更改递归以输出正确的简化表达式?
你的情况没有被涵盖,所以你得到默认值,一直到最后:简化左边,简化右边,然后 return 那。
问题是,您简化了左侧节点,将 (T ↓ y)
变为 F
,右侧节点(没有变化),但是您无法继续应用简化:您只是 return lhs ↓ rhs
, 不简化这个.
一个非常简单的调试运行应该已经找到了,不是吗?也许下次尝试阅读您的代码并在达到 SO 之前多逐步执行它。
就其价值而言,我将在此处进行 2 项重大改进:
我会从里到外工作,这几乎从定义上讲更聪明,因为您的简化规则都只适用于非复杂节点。
因此,我会采用您的左右节点,首先简化它们,然后 运行 您的简化规则。这样就无需简化最终结果。
因此,不要在一百万个地方传递 super.getRight()
,而是从:
Node left = getLeft().simplify();
Node right = getRight().simplify();
然后检查你的规则,这次只使用左和右(与 super.getLeft().simplify()
相比)。如果你的规则中的 none 适用,则进一步的简化不会帮助你,所以你可以 return new Nor(left, right)
,然后就可以完成了。
第二个主要更新:toString()
是一个调试/日志工具 仅 - 与 toString 相比,对业务逻辑进行编程必然会破坏行为,即使它不是直接错误。因此,通过 getLeft().toString().equals("T")
检查 'is the left node the node representing a constant TRUE value' 是糟糕的代码风格,并且会自找麻烦。
应该有一个正确的方法来检查这个。可能是 if (left.isConstantTrue())
或者 if (left.equals(Node.TRUE))
,或者可能是 if (left instanceof Constant c && c.value)
(这是 JDK16 语法,没有 JDK16 就很啰嗦:if ((left instanceof Constant) && ((Constant) left).value)
.
None 其中依赖于调试辅助代码永远不会更改,并且任何其他节点也永远不会打印 T
,并且通常将您的代码修复为惯用的,而不是一个会触发所有 linter 工具的东西。
此外,super
调用很奇怪。您有时调用 super.getRIght
,有时调用 this.getRight
。通常,除非有特定原因,否则不要指定 this/super。为什么要跳过 getRight
的任何本地覆盖?您可能没有/您甚至可能 没有 覆盖,这使得 super.getRight()
、this.getRight()
和 getRight()
都 100% 等效。只需写 getRight()
- 与您的语义意图相匹配,即 'get the Right node',而不是 'get the superclass impl of getRight, intentionally skipping past any custom modifications this instance has performed'.