繁体   English   中英

使用位运算符递归

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM