我尝试了一些不同的方法,包括创建一个单独的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}"
请确保下次将代码分解为较小的块并单独测试它们。这将有助于您查明问题。由于这些逻辑门的东西带回了记忆,我无法帮助自己并自己实现它并写了一个冗长的答案:-)
我对你的代码做了一些改进(我称之为:-)):
由于你有不同数量的输入,我不会让你的父类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
AndGate
和OrGate
支持任意数量的输入:
p AndGate.new(true, true, true).call # => true
如果您不喜欢这个......那么您可以限制输入...
另请注意,我将cir_func
重命名为call
。这有两个原因:
但是你当然可以随意改变它。
现在,您可以编写一些测试来验证行为:
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
的代码。
这是一个有效的半加法器。您可以在没有太多复杂性的情况下制作这样的完整加法器 - 也许吧。对于计算机所做的最基本,最简单的事情,我觉得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...