[英]Multiply without multiplication, division and bitwise operators, and no loops. Recursion
[英]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)
。
我需要如何将递归更改为 output 正确的简化表达式?
你的情况没有被覆盖,所以你得到默认值,一直到最后:简化左边,简化右边,然后返回。
问题是,您简化了左侧节点,将(T ↓ y)
转换为F
和右侧节点(没有变化),但是您无法继续应用简化:您只需返回lhs ↓ rhs
,而不进行简化。
一个非常简单的调试运行应该会发现这个,不是吗? 也许下一次尝试阅读您的代码并在达到 SO 之前再逐步完成它。
对于它的价值,我将在这里进行 2 项重大改进:
我会由内而外地工作,这几乎按照定义更聪明,因为您的简化规则都只适用于非复杂节点。
因此,我将采用您的左右节点,首先简化它们,然后运行您的简化规则。 这消除了简化最终结果的需要。
因此,与其在一百万个地方传递super.getRight()
,不如从以下开始:
Node left = getLeft().simplify();
Node right = getRight().simplify();
然后通过你的规则 go ,这次只使用左右 (vs super.getLeft().simplify()
。如果你的规则都不适用,则没有进一步的简化可以帮助你,所以你可以返回new Nor(left, right)
,并完成它。
第二个重大更新: toString()
仅是一个调试/日志工具 - 对您的业务逻辑与 toString 进行编程必然会破坏行为,即使它不是一个直接的错误。 因此,通过getLeft().toString().equals("T")
检查“左节点是代表常量 TRUE 值的节点”是错误的代码风格,并且会在以后遇到麻烦。
应该有适当的方法来检查这一点。 也许是if (left.isConstantTrue())
或者if (left.equals(Node.TRUE))
,或者if (left instanceof Constant c && c.value)
(这是没有 JDK16 的语法: if ((left instanceof Constant) && ((Constant) left).value)
。
这些都不依赖于永远不会更改的调试辅助代码,并且任何其他节点也永远不会打印T
,并且通常将您的代码修复为惯用的,而不是触发每个 linter 工具的东西。
此外, super
调用很奇怪。 你有时调用super.getRIght
,有时你调用this.getRight
。 通常,除非您有特定原因,否则不要指定 this/super。 为什么要跳过getRight
的任何本地覆盖? 您可能没有/您甚至可能没有覆盖,这使得super.getRight()
、 this.getRight( this.getRight()
和getRight()
都 100% 等效。 只需编写getRight()
- 与您的语义意图相匹配,即简单地“获取正确的节点”,而不是“获取 getRight 的超类 impl,有意跳过此实例执行的任何自定义修改”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.