Skip navigation
Page Content:
Mathematik mit Redcode
Die Hauptaufgabe von Computern ist ja eigentlich das Berechnen verschiedenster Dinge. Als Benutzer bemerkt man das vielleicht nicht so direkt, aber als Programmierer hat man ständig damit zu tun. Auch Core War-Kampfprogramme müssen gelegentlich etwas berechnen. Redcode kennt fünf mathematische Instruktionen:
  Mathematische Instruktionen   | Opcode | Bedeutung | 
   | ADD | Addition | 
   | SUB | Subtraktion | 
   | MUL | Multiplikation | 
   | DIV | Ganzzahlige Division | 
   | MOD | Rest einer Division | 
Jeder dieser Befehle verwendet zwei Operatoren, wobei das Ergebnis in der Zelle gespeichert wird, die durch den Operand B ("Target") angegeben ist. Bei Division und Modulo ist zu beachten, daß B ÷ A gerechnet wird.
Die folgenden Beispiele dienen nur der Erklärung, solche Berechnungen kommen normalerweise nicht in Kampfprogrammen vor:
Potenzen
 Da es nur die arithmetischen Grundoperationen als Maschinenbefehle gibt, muß man die höheren Funktionen durch Programme nachbilden. Ein einfaches Beispiel dafür ist die Berechnung einer Potenz be = b * b * ... * b, e-Mal. Also bilden wir eine Programmschleife, die b e-Mal mit sich selbst multiplizert. Dieses Beispiel berechnet p = be, mit b=2 und e=3:  loop   MUL   b,    p    
         DJN   loop, e    
         ... 
  p      DAT   #1         
  b      DAT   #2         
  e      DAT   #3         
 Nach dem die Schleife dreimal durchlaufen wurde, ist e = 0 und in p liegt der Wert #8. Die Werte für b und e können beliebig gewählt werden.
Absoluter Betrag
 Diese Funktion wäre eigentlich auch sehr leicht zu implementieren. Der absolute Betrag einer Zahl ist die selbe Zahl, nur ohne Vorzeichen. Also: |n| ist gleich n, wenn n ≥ 0 ist, und n * (-1), wenn n < 0. Ein Programm für diese Berechnung würde so aussehen:
 einer Zahl ist die selbe Zahl, nur ohne Vorzeichen. Also: |n| ist gleich n, wenn n ≥ 0 ist, und n * (-1), wenn n < 0. Ein Programm für diese Berechnung würde so aussehen:  start     SLT   #0,    n    
  skipless  MUL   #-1,   n    
            ... 
  n         DAT   #123
 Dieses nette Programm funktioniert in einem MARS-Computer allerdings nicht, denn...
Negative Zahlen
 gibt es im Krieg der Kerne nicht. Weil der Speicher ringförmig aufgebaut ist, ist es egal, ob man eine Zelle zurück geht, oder CORESIZE-1 Zellen nach vorne. Werte, die z. B. durch Addition oder Subtraktion ausserhalb des Bereiches 0 ... CORESIZE-1 zu liegen kommen, werden vom MARS automatisch modulo CORESIZE gerechnet, d. h. sie werden auf den Rest der Division durch CORESIZE gekürzt: n ← n % CORESIZE. Negative Zahlen werden dabei in den positiven Bereich "verschoben". ARES zeigt allerdings negative Zahlen an - sofern man nicht mit STRG-I auf Anzeige absoluter Werte umschaltet. Üblicherweise wird Core War mit einer Speichergröße von 8000 Zellen gespielt. In diesem Fall werden alle Werte ab 4000 von ARES als negative Werte angezeigt, was meistens auch sinngemäß ist. Negative Werte n sind also als 8000 - n zu verstehen.
 Wenn man unbedingt mit negativen Zahlen arbeiten möchte, kann man auch in einem MARS-Programm einfach vorsehen, daß alle Werte die größer als 4000 sind, als negative Zahlen betrachtet werden. Der eigentliche Wert dieser Zahl ist dann der Abstand zu 8000 und der absolute Wert ist durch die Formel Abs(n) = 8000 - n gegeben.
 Ein Programm zur Berechnung des Absolutwertes könnte daher so aussehen:  start   SLT   #CORESIZE/2,   n       
          JMP   done                   
          SUB   n,             temp    
          MOV   temp,          n       
  done    ... 
  n       DAT   #-1000 
  temp    DAT   #CORESIZE              
Primzahlen
 Die Aufgabe, festzustellen, ob eine Zahl eine Primzahl ist, ist schon etwas schwieriger zu lösen: Eine Primzahl zeichnet sich bekanntlich dadurch aus, daß sie nur durch sich selbst und durch Eins teilbar ist. Das folgende Programm testet zunächst, ob bei der Division der Zahl n durch 2 ein Rest bleibt. Wenn nicht, dann handelt es sich um eine gerade Zahl. Falls ein Rest geblieben ist, prüft die Routine die Division durch alle ungeraden Zahlen, bis entweder eine Division keinen Rest hat oder eine Division durch n getestet wird. Sollte bis dahin keine Teilbarkeit durch eine der kleineren ungeraden Zahlen gefunden worden sein, so handelt es sich um eine Primzahl. (Das folgende Programm verwendet Opcode Modifiers, die bisher noch nicht erklärt wurden)
 ist, ist schon etwas schwieriger zu lösen: Eine Primzahl zeichnet sich bekanntlich dadurch aus, daß sie nur durch sich selbst und durch Eins teilbar ist. Das folgende Programm testet zunächst, ob bei der Division der Zahl n durch 2 ein Rest bleibt. Wenn nicht, dann handelt es sich um eine gerade Zahl. Falls ein Rest geblieben ist, prüft die Routine die Division durch alle ungeraden Zahlen, bis entweder eine Division keinen Rest hat oder eine Division durch n getestet wird. Sollte bis dahin keine Teilbarkeit durch eine der kleineren ungeraden Zahlen gefunden worden sein, so handelt es sich um eine Primzahl. (Das folgende Programm verwendet Opcode Modifiers, die bisher noch nicht erklärt wurden)  start       MOV     n,           temp 
              MOD     #2,          temp     
              JMZ     not_prime,   temp     
  loop        MOV     n,           temp 
  check       MOD     #3,          temp     
              JMZ     not_prime,   temp     
              ADD.a   #2,          check    
              SLT.ab  check,       n        
              JMP     is_prime              
              JMP     loop                  
  temp        DAT   #0 
  n           DAT   #73*73
  not_prime   ... 
  is_prime    ... 
 Es sei noch angemerkt, daß dieses Programm die Aufgabe nicht optimal löst: Zum einen bräuchte man nicht durch 9 dividieren, wenn schon festgestellt wurde, daß die Zahl nicht durch 3 teilbar ist. Zum anderen könnte man aufhören zu probieren, wenn man bereits erfolglos versucht hat, n durch die abgerundete Wurzel von n zu dividieren.
→ Multitasking
  
  Content Management:
  μCMS α1.6