2016-05-09 9 views
0

Ich habe ein paar verschiedene Ansätze ausprobiert, einschließlich der Erstellung einer separaten NANDGate-Klasse und der Verwendung von NOR-Gates, aber ich kann wirklich nicht herausfinden, wo ich falsch liege. Mein Wert für die Addiererausgabe wird immer als Boolescher Wert zurückgegeben, und das Carryout-Ergebnis ist für bestimmte Eingaben nicht korrekt. Ich stelle mir vor, dass das Problem in der XOR-Klasse liegt, die ich habe. Wenn jemand mich in die richtige Richtung bringen kann, würde es sehr geschätzt werden. Hinweis I Ruby sehr unerfahren bin das ist meine zweite Zeit-Codierung darinErstellen einer XOR-Klasse zum Implementieren eines Volladdierers

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}" 
+2

Sie sollten bitwise Operatoren ('&', '|', '~') anstelle von logischen Operatoren ('&&', '||', '!') Oder Schlüsselwörtern ('and',' or') verwenden. 'not'), wenn Sie ganzzahlige Rückgabewerte wünschen. – Aetherus

+0

Beachten Sie, dass "gets" eine Zeichenfolge zurückgibt. Sie müssen wahrscheinlich die Eingabe in eine Zahl/boolean konvertieren (es gibt eine unbenutzte Methode 'Boolean' in Ihrem Code) – Stefan

Antwort

0

Bitte stellen Sie sicher, dass Sie das nächste Mal Ihren Code in kleinere Stücke brechen und testen sie in der Isolation. Dies wird Ihnen helfen, das Problem zu lokalisieren. Da dieses logische Gate-Zeug Erinnerungen zurückbringt, konnte ich mir nicht helfen und implementierte es alleine und schrieb eine lange Antwort :-)

Ich habe einige Verbesserungen vorgenommen (ich würde es so sagen :-)) Ihr Code:

Da Sie unterschiedliche Anzahlen von Eingängen haben, würde ich nicht Ihre Elternklasse Circuit nehmen eine bestimmte Anzahl von Eingaben und dann überschreiben, um diese Zahl zu ändern. Entfernen Sie entweder die Elternklasse (meine bevorzugte Methode) oder lassen Sie sie eine variable Anzahl von Eingaben akzeptieren. Dies hat einige Vorteile, aber auch Nachteile (müssen die Eingänge als inputs[0] und so weiter zugreifen Sie könnten durch die Bereitstellung Accessoren dieses Problem umgehen.):

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 

Weil sie eine Elternklasse entschieden implementiert ich einige Proben mit dieser Technik :

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 

Die AndGateOrGate und unterstützt eine beliebige Anzahl von Eingängen:

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

Wenn Ihnen das nicht gefällt ... dann können Sie die Eingaben einschränken ...

Beachten Sie auch, dass ich cir_func in call umbenannt habe. Dies ist aus zwei Gründen:

  • Ich weiß nicht, was cir steht für
  • Ich mag sie nicht abgekürzt Methodennamen (func)

aber natürlich können Sie ändere das so, wie es dir gefällt.

Jetzt können Sie einige Tests schreiben, das Verhalten zu überprüfen:

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 

ich für einen Super Test entschieden haben, die eine Hilfsmethode, die eine logische Tabelle zu behaupten, zur Verfügung stellt.

Mit den Grundgatter anstelle können Sie beginnen, die Verbund diejenigen zu bauen:

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

und einige komplexere:

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 

und die Tests für diejenigen:

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 

Und schließlich können wir den Volladdierer mit seinem Test implementieren:

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 

Sie könnten diese Methode durch die Zuordnung/Wiederverwendung von Zwischenergebnissen schrumpfen, aber ich konnte nicht von cleveren Namen denken, so dass ich nicht dieses :-) zu tun hat

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 

Achtung: Für Ihre Code, den Sie sicherstellen möchten, dass Sie die Eingabe konvertieren, die Sie über gets in booleans lesen. Sie haben dort bereits einen Code mit Boolean.