Multiplikation

Alles, was nicht direkt mit Python-Problemen zu tun hat. Dies ist auch der perfekte Platz für Jobangebote.
Antworten
fail
User
Beiträge: 122
Registriert: Freitag 11. Januar 2013, 09:47

Multiplikationsalgorithmus ohne * oder module zu benutzen.

Funktioniert für [-999999,.....,-2,-1,0,1,2,.......,999999]

Code: Alles auswählen

def multiplication(a,b):
	if b>=0:
		return sum(a for _ in range(b))
	elif a<0 and b<0:
		return sum(-a for _ in range(-b))
	else:
		return sum(b for _ in range(a))
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du hast im Prinzip drei identische Zeilen, welche jeweils die Summe bilden. Daher solltest du diese aus den if/elif/else-Blöcken rausziehen und darin nur die Dinge behandeln, welche tatsächlich unterschiedlich sind.

Auch, wenn es sich hier nur um Spielerei handelt: probiere mal ``multiplication(1, 1000000000)`` und ``multiplication(1000000000, 1)`` aus und überlege dir, warum sich die Aufrufe unterschiedlich verhalten.
fail hat geschrieben:Funktioniert für [-999999,.....,-2,-1,0,1,2,.......,999999]
Was willst du damit sagen? Dass es für alle ganzen Zahlen funktioniert?
Das Leben ist wie ein Tennisball.
fail
User
Beiträge: 122
Registriert: Freitag 11. Januar 2013, 09:47

Ja, es funktioniert nur für ganze zahlen.
Meinst du das die kleinere Zahl im range() sein sollte?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

fail hat geschrieben:Meinst du das die kleinere Zahl im range() sein sollte?
Ja, das wäre geschickter. Aber das Beispiel ist ja eh nur akademischer Natur.
Das Leben ist wie ein Tennisball.
BlackJack

@fail: Es gibt übrigens noch eine effizientere Methode die mit Bit-Verschiebungen und Addition auskommt. Also die Operatoren ``<<``, ``>>``, und ``+``.
fail
User
Beiträge: 122
Registriert: Freitag 11. Januar 2013, 09:47

Ist das Cheating

Code: Alles auswählen

def multiplication(a,b):
	return a/(1/b)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Nein, das ist eine nichtfunktionierende Lösung (b=0). Davon abgesehen handelst du dir natürlich die üblichen Probleme mit floats ein.
Das Leben ist wie ein Tennisball.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

BlackJack hat geschrieben:@fail: Es gibt übrigens noch eine effizientere Methode die mit Bit-Verschiebungen und Addition auskommt. Also die Operatoren ``<<``, ``>>``, und ``+``.
Als Fingerübung kann man auch gleich die Addition mittels Bitoperatoren mit umsetzen. Interessant dürften da AND (&) und XOR (^) sein. :D
fail
User
Beiträge: 122
Registriert: Freitag 11. Januar 2013, 09:47

Ich schaff die addition einfach nicht. Ich hab schon alles versucht. Der Fehler ist wahrscheinlich in der Addition funktion, aber ich kann ihn nicht finden.

Code: Alles auswählen

from functools import reduce

def addition(a,b):
    a = list(map(int,list(bin(a)[2:])))
    b = list(map(int,list(bin(b)[2:])))
    remainder = 0
    resultat=[]
    for c in reversed(range(max(len(a),len(b)))):
        resultat.append(adder(get(a,c),get(b,c),remainder)[0])
        remainder=adder(get(a,c),get(b,c),remainder)[1]
    return bin2dec(list(reversed(resultat)))

def adder(a,b,cin):
    s=cin ^ a ^ b
    cout=(a&b)| (cin&(a^b))
    return s,cout

def get(von,das):
    try:
        return von[das]
    except IndexError:
        return 0

def bin2dec(binary):
        return reduce(lambda acc,y: acc*2 + y,binary)        
        
BlackJack

@fail: Ich würde es ja nicht mit einzelnen Bits in einer Liste machen sondern mit den Zahlen und den Bitoperationen selbst, denn die werden intern ja schon binär gespeichert.

Edit:

Code: Alles auswählen

def add(a, b):
    while True:
        a, b = a ^ b, b & a
        if b == 0:
            return a
        b <<= 1
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@fail:
Das ist viel zu kompliziert gedacht. Schau Dir mal einen Halbaddierer an. Das kann man gut übertragen.

Edit:
Kleine Ergänzung, um den Überlauf für bestimmte Vorzeichensituationen loszuwerden:

Code: Alles auswählen

def add(a, b):
    if a == -b:
        return 0
    if a < b:
        a, b = b, a
    if a > 0 and b < 0:
        if -b < a:
            return -add(-a, -b)
    while True:
        a, b = a ^ b, b & a
        if b == 0:
            return a
        b <<= 1
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

@jerch: Du benutzt doch in deinem Code ständig "-", das ist doch unfair :p Dann geht auch

Code: Alles auswählen

add = lambda a, b: a - (-b)
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Die Klammern sind überflüssig:

Code: Alles auswählen

>>> a, b = 23, 42
>>> a--b
65
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

derdon hat geschrieben:Die Klammern sind überflüssig:

Code: Alles auswählen

>>> a, b = 23, 42
>>> a--b
65
Und woher soll Python dann wissen, ob nicht (a-)-b gemeint war????
BlackJack

@nomnom: Öhm, das wäre ein `SyntaxError`:

Code: Alles auswählen

n [86]: (a-)-b
  File "<ipython-input-86-e4fa2a309856>", line 1
    (a-)-b
       ^
SyntaxError: invalid syntax
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

nomnom hat geschrieben:@jerch: Du benutzt doch in deinem Code ständig "-", das ist doch unfair :p Dann geht auch

Code: Alles auswählen

add = lambda a, b: a - (-b)
Ok, Abkürzungen gelten nicht:

Code: Alles auswählen

ZERO = 0
ONE = 1

# simple 1 testing
def is_one(a):
    return ONE if a==ONE else ZERO

# xor equal testing
def equal(a, b):
    return is_one(((a^b) << ONE) | ONE)

# testing for zero (lazy version with using equal)
def is_zero(a):
    return equal(a, ZERO)

# simple incrementor
def inc(a):
    if equal(a, ~ZERO):
        return ZERO
    b = ONE
    while ONE:
        if is_zero(b):
            return a
        a, b = a^b, (a&b) << ONE

# negativate number: positive to negative and negative to positive
def neg(a):
    if is_zero(a):
        return a
    return inc(~a)
Jetzt kannst Du das '-' mit neg() ersetzen. Damit kannst Du die komplette Intergerarithmetik auf Bitoperatoren und den basalen 1 oder 0 Test zurückführen. Hochintegrierte ALUs waren gestern, hoch leben die Register ;)
(Zur Anschaulichkeit hab ich 1 und 0 mal durch "Konstanten" ersetzt)
Antworten