创建XOR类以实现完整加法器

问题描述 投票:0回答:2

我尝试了一些不同的方法,包括创建一个单独的NANDGate类,并使用NOR Gates,但我真的无法弄清楚我的方法在哪里出错。我的加法器输出值继续作为布尔值返回,并且执行结果对于某些输入是不正确的,我想这是因为问题出在我所拥有的XOR类中。如果有人能把我放在正确的方向,我们将非常感激。注意我对Ruby非常缺乏经验,这是我的第二次编码

class Circuit
   # constructor method
   def initialize(in1, in2)
      @in1, @in2 = in1, in2
   end
end

class AndGate < Circuit

   def cir_func()
      (@in1 && @in2)
   end
end

class OrGate < Circuit

   def cir_func()
      (@in1 || @in2)
   end
end

class NotGate < Circuit
   def initialize(in1)
      @in1 = in1
   end

   def cir_func()
      (not @in1)
   end
end

class NandGate < Circuit

  def cir_func()
    (not (@in1_ && @in2_))
  end

end

class XOrGate < Circuit
  def initialize(in1, in2)
    @in1_ = in1
    @in2_ = in2
  end

  def cir_func()
    a0 = AndGate.new(@in1_, @in2_).cir_func()
    a0not = NotGate.new(a0).cir_func()
    a1 = AndGate.new(@in1_, a0not).cir_func()
    a1not = NotGate.new(a1).cir_func()
    a2 = AndGate.new(a0not, @in2_).cir_func()
    a2not = NotGate.new(a2).cir_func()
    o0 = AndGate.new(a1not, a2not).cir_func()
    o0not = NotGate.new(o0)
    return o0not.cir_func()
  end
end

class Mux_2to1 < Circuit

  def initialize(in1, in2, ctr1)
    @in1_ = in1
    @in2_ = in2
    @ctr1_ = ctr1
  end

  def cir_func()
    inv_ctr = NotGate.new(@ctr1_).cir_func()
    a0 = AndGate.new(@in1_, inv_ctr).cir_func()
    a1 = AndGate.new(@in2_, @ctr1_).cir_func()
    o0 = OrGate.new(a0, a1)
    return o0.cir_func()
  end
end

class Mux_4to1 < Circuit

  def initialize(in1, in2, in3, in4, ctr1, ctr2)
    @in1_ = in1
    @in2_ = in2
    @in3_ = in3
    @in4_ = in4
    @ctr1_ = ctr1
    @ctr2_ = ctr2
  end
  def cir_func()
    a0 = Mux_2to1.new(@in1_, @in2_, @ctr1_).cir_func()
    a1 = Mux_2to1.new(@in3_, @in4_, @ctr1_).cir_func()
    o0 = Mux_2to1.new(a0, a1, @ctr2_)
    return o0.cir_func()
  end
end

class FullAdder < Circuit

  def initialize(in1, in2, carryIn)
    @in1_ = in1
    @in2_ = in2
    @carry_ = carryIn
  end
  def cir_func()
    a0 = XOrGate.new(@in1_, @in2_).cir_func()
    o0 = XOrGate.new(a0, @carry_)
    a1 = AndGate.new(@in1_, @in2_).cir_func()
    a2 = AndGate.new(a0, @carry_).cir_func()
    o1 = OrGate.new(a1, a2)
    return o0.cir_func(), o1.cir_func()
  end
end


def Boolean(string)
  return true if string== true || string =~ (/(true|1)$/i)
  return false if string== false || string.nil? || string =~ (/(false|0)$/i)
  raise ArgumentError.new("invalid value for Boolean: \"#{string}\"")
end

puts "Please enter input 1 for adder:"
input_1 = gets()

puts "Please enter input 2 for adder:"
input_2 = gets()

puts "Please enter carry in for adder:"
carryin_ = gets()

x = FullAdder.new(input_1, input_2, carryin_)
output, carryOut = x.cir_func()
puts "The result for the adder is: #{output} and the carry out is: #{carryOut}"
ruby xor
2个回答
0
投票

请确保下次将代码分解为较小的块并单独测试它们。这将有助于您查明问题。由于这些逻辑门的东西带回了记忆,我无法帮助自己并自己实现它并写了一个冗长的答案:-)

我对你的代码做了一些改进(我称之为:-)):

由于你有不同数量的输入,我不会让你的父类Circuit采取特定数量的输入,然后覆盖以更改该数字。删除父类(我的首选方式)或使其接受可变数量的输入。这有一些好处,但也有缺点(需要以inputs[0]等方式访问输入。你可以通过提供访问器来解决这个问题):

class Circuit
  def initialize(*inputs)
    @inputs = inputs
  end

  def call
    raise "Please implement in #{__FILE__}"
  end

  def inspect
    "#{self.class.name}: #{inputs.join(', ')} => #{call}"
  end

  private

  attr_reader :inputs
end

因为您选择了父类,所以我使用这种技术实现了一些示例:

class AndGate < Circuit
  def call
    inputs.inject do |memo, input|
      memo &&= input
      memo
    end
  end
end

class OrGate < Circuit

  def call
    inputs.inject do |memo, input|
      memo ||= input
      memo
    end
  end
end

class NotGate < Circuit
  def call
    !inputs[0]
  end
end

AndGateOrGate支持任意数量的输入:

p AndGate.new(true, true, true).call # => true

如果您不喜欢这个......那么您可以限制输入...

另请注意,我将cir_func重命名为call。这有两个原因:

  • 我不知道cir代表什么
  • 我不喜欢缩写的方法名称(func)

但是你当然可以随意改变它。

现在,您可以编写一些测试来验证行为:

require 'minitest/autorun'
class GateTest < Minitest::Test
  def assert_table(klass, table)
    table.each do |inputs, outputs|
      gate = klass.new(*inputs)
      assert_equal outputs, gate.call, "Expected #{klass} to convert #{inputs} to #{outputs}"
    end
  end
end

class AndGateTest < GateTest

  def test_gate
    table = {
      [false, false] => false,
      [false, true] => false,
      [true, false] => false,
      [true, true] => true
    }
    assert_table(AndGate, table)
  end

end
class OrGateTest < GateTest

  def test_gate
    table = {
      [false, false] => false,
      [false, true] => true,
      [true, false] => true,
      [true, true] => true
    }
    assert_table(OrGate, table)
  end

end

class NotGateTest < GateTest

  def test_gate
    table = {
      [false] => true,
      [true] => false,
    }
    assert_table(NotGate, table)
  end

end

我选择了一个超类测试,它提供了一个帮助方法来断言逻辑表。

有了基本的门,你可以开始构建复合门:

class NandGate < Circuit
 def call
   NotGate.new(
    AndGate.new(*inputs).call
  ).call
 end
end

还有一些更复杂的:

class XOrGate < Circuit
  def call
    OrGate.new(
      AndGate.new(
        NotGate.new(inputs[0]).call,
        inputs[1]
      ).call,
      AndGate.new(
        inputs[0],
        NotGate.new(inputs[1]).call
      ).call
    ).call
  end
end

那些测试:

class NandGateTest < GateTest

  def test_gate
    table = {
      [false, false] => true,
      [false, true] => true,
      [true, false] => true,
      [true, true] => false
    }
    assert_table(NandGate, table)
  end

end

class XOrGateTest < GateTest

  def test_gate
    table = {
      [false, false] => false,
      [false, true] => true,
      [true, false] => true,
      [true, true] => false
    }
    assert_table(XOrGate, table)
  end

end

最后,我们可以通过测试实现全加器:

class FullAdderGate < Circuit
  def call

    sum = XOrGate.new(
      inputs[2],
      XOrGate.new(
        inputs[0],
        inputs[1]
      ).call
    ).call

    carry = OrGate.new(
      AndGate.new(inputs[0], inputs[1]).call,
      AndGate.new(
        XOrGate.new(inputs[0], inputs[1]).call,
        inputs[2]
      ).call
    ).call

    [carry, sum]
  end

end

您可以通过分配/重新使用中间结果来缩小此方法,但我想不出聪明的名字所以我没有这样做:-)

class FullAdderGateTest < GateTest

  def test_gate
    table = {
      [false, false, false] => [false, false],
      [false, false, true] => [false, true],
      [false, true, false] => [false, true],
      [false, true, true] => [true, false],
      [true, false, false] => [false, true],
      [true, false, true] => [true, false],
      [true, true, false] => [true, false],
      [true, true, true] => [true, true],
    }
    assert_table(FullAdderGate, table)
  end

end

注意:对于您的代码,您需要确保将通过gets读取的输入转换为布尔值。你已经有了Boolean的代码。


0
投票

这是一个有效的半加法器。您可以在没有太多复杂性的情况下制作这样的完整加法器 - 也许吧。对于计算机所做的最基本,最简单的事情,我觉得30页代码没有充分的理由。

#resulting values, do not set
sum0 = false
carry = false


#binary (set)
a = true
b = true

if a ^ b        #this is the equivalent of XOR
  sum0 = true
  carry = false
end

if a && b
  sum0 = false
  carry = true
end

#expand from here...
© www.soinside.com 2019 - 2024. All rights reserved.