Python rechnet uneffizient?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Haolong
User
Beiträge: 17
Registriert: Dienstag 26. Januar 2016, 14:49

Gute Abend,

Mein Kumpel und ich haben heute je ein Programm geschrieben, dass die Summe aller Primzahlen zwischen 2 und 2.000.000 berechnet.
Er prorammierte in Java und ich in Python. Erstaunlicherweise war sein um einiges schnell durch gelaufen als meins. Seins war ca nach 25. Minuten fertig, meins rodelt nach 4,5 Stunden immer noch und ist erst bei Zahl 1,5 Mio angekommen. Ich werde euch natürlich die Codes von beiden Programmen sowie die Rechenleistungen der PCs auflisten:

Java Programm Rechner:
CPU Chris: i7 -3610QM @2.3 GHz
8 GB RAM

Java Programm:

Code: Alles auswählen

package prime;

import java.util.ArrayList;

public class testPrime {

 public double zahl;
 public int value;
 ArrayList<Integer> eineListe = new ArrayList<Integer>();
 // i = Zähler
 // t = Nenner
 //zahl = zähler/Nenner
 //Nenner<Zähler
 

 public void zahl(){

  
  eineListe.add(2);
  
  int check;

  
  for(double i=2;i<2000000;i++){
   
   check = 0;
   for(int t=0;t<eineListe.size();t++){

    zahl = i/eineListe.get(t);
    int x = (int)zahl;
    if( (zahl==x)){
    check=1;
    
    }
   
   }
   
   if(check==0){
   
    System.out.println(i);
    value= (int) (value+i);
    eineListe.add((int) i);
   }
   
  }
  System.out.println(value);
  
}
}
Python Programm Rechner:

i5-4690 @ 3.5GHz
16 GB RAM

Python Programm:

Code: Alles auswählen

liste = [2]
summe = 2
for i in range(2, 2000000):
    print(i)
    error = 0
    for j in liste:
        div = i % j
        if div == 0:
            error = 1

    if error == 0:
        liste.append(i)
        summe += i

print("---------")
print(liste)
print(summe)

Unterscheide die mir klar sind:

-Ich benutze den Modulo Operator um zu überprüfen, ob eine Zahl eine Primzahl ist, während mein Kumpel mit int-Konvertieren überprüft.
-Ich lasse jede Zahl printen, während mein Kumpel nur alle Primzahlen printet.

Woran liegt es also, dass sein Programm nach ca. 25 Minuten fertig ist und meines erst nach geschätzt 6 Stunden? Liegt es daran, dass ich viel mehr printe? Oder an den Rechnern? Oder an der Sprache?

Wäre für jede Erklärung dankbar :)

Gruß,

Hao

edit1: Kumpel hatte falsches Ergebnis bekommen, da er int statt double für "value" benutzt hat. Programm läuft aber immer noch genauso schnell.
Nitrama
User
Beiträge: 6
Registriert: Donnerstag 3. Dezember 2015, 15:47

Hallo,

ich kann dir aus meiner Erfahrung sagen das Print wirklich recht lange dauert.
Aber das ist nicht das Hauptproblem.
Python Rechnet nicht uneffizient.
Die Verfahrensweise ist einfach uneffizient.
Ich habe mal kurz gegoogelt und bin auf das gestoßen.
https://de.wikibooks.org/wiki/Primzahle ... mbeispiele

Da gibts auch eine Java Version! Mich würden die neuen Zeiten Interressieren :-)

Gruß Nitrama

PS: Leicht angepasste Version von Wikibooks.

Code: Alles auswählen

def main():
    # Frage den Benutzer nach einer Obergrenze bis zu der gesucht werden soll
    while True:
        try:
            obergrenze = int(input('Bitte geben Sie eine Obergrenze ein: '))
            break
            
        except ValueError:
            print ('Dies ist keine gültige Obergrenze. Bitte verwenden Sie eine Ganzzahl!')
    
    # Jede Zahl zwischen 1 und obergrenze wird zuerst als prim angenommen
    zahlen = [True]*(obergrenze+1)
    # Da 0 und 1 keine Primzahlen sind, werden sie auf False gesetzt
    zahlen[0] = False
    zahlen[1] = False
    
    i = 2
    
    while i*i <= obergrenze:
        if zahlen[i] == True: # Die Zahl i ist als prim markiert
            # Streiche alle Vielfachen von i
            for k in range(i*i,obergrenze+1,i):
                zahlen[k] = False
        
        i = i+1
    
    # Ausgabe aller gefundenen Zahlen
    for i, v in enumerate(zahlen):
        if v == True:
            print (i, 'ist prim.')
    
    return 0

if __name__ == '__main__':
    main()
Haolong
User
Beiträge: 17
Registriert: Dienstag 26. Januar 2016, 14:49

Mein Kumpel und ich benutzen doch die gleiche Verfahrensweise. Warum ist sein Programm dann 14 mal schneller als meins?

Nach 7,5 Stunden war mein Programm durch und hat sich beim Printen der Liste aller Primzahlen aufgehängt :(
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Die JVM ist wesentlicher schneller als CPython. Du könntest PyPy nutzen was wesentlich schneller wäre.
hans
User
Beiträge: 728
Registriert: Sonntag 22. September 2002, 08:32
Wohnort: Sauerland
Kontaktdaten:

Bei den von Nitrama gegeben Beispielen fällt folgenes auf:

Code: Alles auswählen

for(unsigned i=2; i<=limit; ++i) Stroke[i] = 0;
Warum prüft man bei Zahlen wie 2,4,6,8,10,12,...... auf Primzahl? Die sind von vornherein durch 2 teilbar. Also könnte ich beginnend bei i= 1 oder i=3 den Wert von i gleich um 2 statt 1 erhöhen. Das spart 50% der Prüfungen. Oder habe ich da etwas übersehen?
BlackJack

@hans: Nein, da hast Du nichts übersehen. Die 2 gesondert zu behandeln und ansonsten gerade Zahlen nicht zu beachten ist eine offensichtliche Optimierung.
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@Haolong: Ja, Java kann effizienter ausgeführt werden, da zur Compilezeit besser optimieren kann und der Just-In-Time-Compiler der Java-Virtual-Machine direkter in Maschinenbefehle übersetzen kann, als das bei Python möglich wäre. Zudem verwendet die Virtuelle Maschine von CPython gar keine Just-in-Time-Compilation. Die Effizienz von Python liegt aber auch nicht in der Ausführungsgeschwindigkeit sondern in der Geschwindigkeit, in der Programmierer Code schreiben können. Schau Dir einfach mal beide Versionen Eueres Algorithmus an. Python 16 Zeilen, Java 48 Zeilen.

Da bei den meisten Aufgaben die Ausführungsgeschwindigkeit keine so großen Unterschiede macht, wie bei reinen mathematischen Spielereien, ist die Programmiereffizienz im Normalfall viel wichtiger.

PS: ein effizienter Primzahlalgorithmus rechnet Dir die Summe, egal ob mit Java oder mit Python programmiert wurde, in weniger als 1 Sekunde aus.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Geht auch in Javascript recht flott:

Code: Alles auswählen

function getPrimes(n) {
    n += 1;
    var sieve = new Uint8Array(n);
    var n_sqrt = Math.floor(Math.sqrt(n-1)) + 1;
    for (var i=2; i<=n_sqrt; ++i) {
        if (!sieve[i]) {
            for (var j=i*i; j<=n; j=j+i)
                sieve[j] = 1;
        }
    }
    var result = [];
    for (var k=2; k<sieve.length; ++k) {
        if (!sieve[k])
            result.push(k);
    }
    return result;
}

var d = new Date();
console.log(getPrimes(2000000));
console.log((new Date())-d);
BlackJack

@Haolong: Java ist eine statisch typisierte Programmiersprache deren Standard-VM aus dem Bytecode vor der Ausführung Maschinencode erzeugen kann. Das heisst wenn da eine Addition steht, dann weis Java was für Typen die Argumente haben und kann bei `int` oder `double` Maschinencode erzeugen der zwei Zahlen addiert.

Python ist eine dynamisch typisierte Programmiersprache deren Standard-VM den vom Compiler erzeugten Bytecode interpretiert. Das heisst wenn da eine Addition steht, dann muss Python erst einmal heraus finden welchen Typ die Argumente haben, beziehungsweise dynamisch den ersten Typ ”bitten” die Addition von den beiden Werten durchzuführen. Und zwar jedes mal aufs Neue wenn der Code an dieser Addition vorbei kommt. So etwas kostet natürlich Zeit. Ausserdem ist Python's `int`-Datentyp nicht auf die Grösse eines Prozessorregisters beschränkt, was dazu führen kann, dass selbst wenn die Typen statisch bekannt wären, es passieren kann, dass eine simpler Maschinencode der zwei ganze Zahlen mit fester Bitgrösse addiert, die in Prozessorregister passen müssen, gar nicht möglich ist.

Bei CPython 2.x kann man den JIT-Compiler Psyco als Modul installieren/importieren um zur Laufzeit zu versuchen Maschinencode erzeugen zu lassen, oder die PyPy-Python-Implementierung. Beide versuchen Typen dynamisch zur Laufzeit zu ermitteln und Maschinencode zu erzeugen der schneller ist als das Interpretieren des Bytecodes. Psyco wird nicht mehr weiterentwickelt (der Entwickler ist bei PyPy aktiv) und nur für 32-Bit-Code verfügbar.

Grundsätzlich habt ihr beide einen nicht gut passenden Algorithmus gewählt, und bei dem dann auch noch einen Fehler gemacht der ihn sehr ineffizient werden lässt. Unpassend deswegen weil ein Sieb schneller ist, während Euer Algorithmus sich eher für Fälle eignet wo man die Obergrenze nicht kennt, also nicht wüsste wie man das Siebt dimensioniert um das Ergebnis sicher darin zu haben. Der Fehler ist die Schleife welche den aktuellen Kandidaten gegen die bereits bekannten Primzahlen testet: die läuft immer komplett durch! Die kann und sollte man abbrechen sobald bekannt ist, dass ein Kandidat keine Primzahl sein kann!

Zu den Quelltexten: Der Java-Quelltext ist lausig/falsch eingerückt. Welche IDE lässt einen das denn *so* eingeben? Man muss sich um Einrückung doch eigentlich gar nicht selber kümmern, im Gegenteil, erfordert es Aufwand Quelltext zu schlecht zu formatieren. ;-)

Die Namen sind schlecht gewählt. `eineListe` sagt dem Leser nicht wirklich was für eine Bedeutung dieses Objekt im Programm hat. Zumal in einer statisch typsierten Programmiersprache der Typ ganz sicher nichts im Namen zu suchen hat, denn den kann der Compiler (und die IDE) sicher zu zuverlässig ermitteln und auf Wunsch anzeigen. Oft beispielsweise als Tooltip wenn man mit der Maus über dem Namen im Quelltext verharrt. Es handelt sich hier um die gefundenen Primzahlen und genau das sollte der Name auch vermitteln, denn *das* kann der Rechner nicht herausfinden und anzeigen.

Wenn man Kommentare braucht die einbuchstabige Namen erklären in dem sie durch ein Gleicheitszeichen getrennt ein einzelnes beschreibendes Wort enthalten, dann sollte vielleicht die Variable mit diesem Wort benannt sein!

Aus OOP-Sicht ist das grosser Murks. Weder `zahl`, noch `value` oder `eineListe` machen den Zustand eines Objektes aus. Das sind alles lokale Variablen einer Funktion, also statischer Methode in Java.

`zahl` ist ein schlechter Methodenname. Methodennamen beschreiben die Tätigkeit die von der Methode verrichtet wird.

`value` sollte eigentlich `result` oder `sum` oder so heissen.

`check` könnte auch einen besseren Namen vertragen aber vor allem auch einen passenderen Datentyp: Das ist ein Wahrheitswert.

Der Test mit Modulo ist deutlich einfacher und auch effizienter.

Die Schleife über die bereits bekannten Primzahlen würde man schon etwas länger nicht mehr so schreiben, mit einer manuell verwalteten Indexvariable. Java kennt schon seit vielen Jahren Syntax für „foreach“-Schleifen.

Das würde in Java dann also eher so aussehen:

Code: Alles auswählen

import java.util.ArrayList;

public class Test {

    public static void main(String args[]) {
        int result = 2;
        boolean isPrime;
        final ArrayList<Integer> primes = new ArrayList<Integer>();
        primes.add(2);

        for (int candidate = 3; candidate < 2000000; candidate += 2) {
            isPrime = true;
            for (int prime : primes) {
                if (candidate % prime == 0) {
                    isPrime = false;
                    break;
                }
            }
            if (isPrime) {
                System.out.println(candidate);
                result += candidate;
                primes.add(candidate);
            }
        }
        System.out.println(result);
    }
}
Etwas unschön ist hier noch das man daran denken muss `result` mit 2 zu initialisieren, weil die zwei aus der Primzahlliste sonst nicht berücksichtigt wird. Hier wäre es besser das Problem besser aufzuteilen und die Summe erst am Ende aus der Liste zu berechnen.

Bei dem Python-Quelltext gibt's auch einige schlechte Namen. Neben `liste` und `i`, die genau so nichtssagend sind wie beim Java-Quelltext, ist `error` hier komisch, denn es handelt sich ja nicht um einen Fehler (auch hier wäre der Typ `bool` angebracht), sondern um die Eigenschaft der Zahle (prim oder nicht).

Einen besseren Namen für `error` braucht man gar nicht suchen weil sich das in Python mit `all()` und einem Generatorausdruck sowieso viel kompakter schreiben lässt:

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function


def main():
    primes = [2]
    for candidate in range(3, 2000000, 2):
        if all(candidate % prime != 0 for prime in primes):
            print(candidate)
            primes.append(candidate)

    print('---------')
    print(primes)
    print(sum(primes))
    

if __name__ == '__main__':
    main()
Haolong
User
Beiträge: 17
Registriert: Dienstag 26. Januar 2016, 14:49

Danke für die ganzen Antworten.

Noch mal kurz erwähnt, wir sind beide Neulinge was Programmieren angeht. Dass das Summe Berechnen von Primzahlen schneller funktionieren kann, ist uns auch beiden klar. Was das Einrücken des Java Codes angeht, das sieht so lausig aus, da er über Skype kopiert wurde und ich diesen dann ins Forum gestellt habe. Das mit den "nichtssagenden" Variablen Namen ist ein guter Punkt. Selbst weiß man natürlich wofür die sein sollen, aber andere verstehen es vlt nicht auf Anhieb. Werden wir uns also merken.

Die einzige Frage die ich ja gestellt hatte war: Warum Java "fast identischen" Code um einiges schneller ausführen kann als Python. Aus euren Antworten habe ich nun herausgelesen, dass das bei Java schneller geht, da der Just-In-Time-Compiler (was immer das auch ist :D) direkte Maschinenbefehle übersetzen kann, was Python nicht kann.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Um es mal anders zu formulieren: Deine Frage ist, warum PKWs schneller beschleunigen als LKWs. Das macht aber nicht viel Sinn, weil es fuer beide Fahrzeuge - und da hoeren die Gemeinsamkeiten halt auf - verschiedene Zielsetzungen gibt.

Das gilt eben auch fuer Programmiersprachen und damit auch fuer Python und Java. Java setzt auf eine schnelle Ausfuehrungsgeschwindigkeit des Programms und Python auf eine schnelle Les- und Schreibgeschwindigkeit des Programmiers.
BlackJack

@Haolong: Man sollte zwischen der Sprache und der Implementierung unterscheiden. Die Standardimplementierung von Java, beziehungsweise der JVM kommt mit einem JIT-Compiler, und die Standardimplementierung von Python tut das nicht. Das heisst nicht, das ”Python” das nicht kann. PyPy wurde ja bereits erwähnt.

Ich habe mal bis auf die Ergebnisausgabe bei beiden Quelltexten die Ausgaben entfernt und beim Java-Quelltext aus dem Ergebnistyp ein `long` gemacht, damit das Ergebnis stimmt. Das hier sind die Zeiten die ich zwischen Oracle's JVM und PyPy messen kann:

Code: Alles auswählen

$ time java Test
142913828922

real    1m56.573s
user    1m56.379s
sys     0m0.112s

$ time pypy test.py
142913828922

real    1m51.335s
user    1m51.039s
sys     0m0.048s
Wie man sieht ist PyPy hier sogar geringfügig schneller.
Haolong
User
Beiträge: 17
Registriert: Dienstag 26. Januar 2016, 14:49

@Blackjack

wow nice, war das mit der gleichen Vorgehensweiße wie wir sie benutzt haben, oder hast du auch einen optimierten Algorithmus benutzt?
BlackJack

@Haolong: Mit den Quelltexten aus meinem Beitrag. Also mit eurer Vorgehensweise allerdings nur jede zweite Zahl getestet, weil die geraden ausser der 2 ganz sicher nicht prim sind, und die erste Schleife abgebrochen sobald das Ergebnis feststeht. Das ihr das nicht gemacht habt, dürfte für die lange Rechenzeit verantwortlich sein.
Haolong
User
Beiträge: 17
Registriert: Dienstag 26. Januar 2016, 14:49

Alles Klar,

Vielen Dank dass ihr mich aufgeklärt habt
Benutzeravatar
miracle173
User
Beiträge: 127
Registriert: Samstag 6. Februar 2016, 00:28

@Haolong:
Ich gehe davon aus, das das die Gesamtzeit im wesentlichen vom print-Statement bestimmt wird.
Es gibt ungefaehr n/ln(n) Primzahlen zwischen 1 und n, also etwa 138000 Primzahlen die kleiner als 2000000 sind. Dein Freund hat für die Ausgabe dieser Zahlen 25 Minuten gebraucht, das sind etwa 25*60/140000 Sekunden, also etwa 0.0109s=10,9ms.
Du hast 1500000 Zahlen ausgegeben. Würde dein Freund das machen, würde er dazu 1500000*0.0109s = 16350s benoetigen, das sind dann 16350/3600 h= 4.54h, als etwa 4,5 Stunden. Da is also nicht viel unterschied. Da du nach 4,5 Stunden 3/4 der Zahlen ausgedrückt hast, würde ich erwarten, dass du in 4.5*4/3= 6 Stunden fertig bist. Da du aber 7,5 Stunden benötigt hast, stimmten meine Annahmen nicht 100-prozentig.
  • Alles in allem sieht man aber, dass man die Programme in verschiedenen Programmiersprachen nur sinnvoll vergleichen kann wenn sie auch wirklich das gleiche tun.
  • Umfangreiche Ausgabe sollte man bei solchen Vergleichen vermeiden, da sie meistens die Gesamtausführungszeit dominiert und von vielen Faktoren/Hardwarekomponenten abhängt. Die Ausgabe auf ein Terminal ist dabei meistens noch wesentlich langsamer als die Ausgabe in eine Datei. Ist also eine umfangreiche Ausgabe unvermeidbar, sollte man sie in eine Datei umleiten. Dies kann bei den meisten Betriebssystemsn mit dem '>' Operator geschehen.
  • Die Ausgabe von 2000000 Zeilen auf den Bildschirm erscheint sowieso nicht sinnvoll. Wenn du auf das Terminal schreibst, weil du wissen willst, wie weit dein Programm ist, dann gib nicht jede Zahl aus, sondern nur jede k-te Zahl. k sollte so gewählt sein, das nur jede Sekunden (oder noch seltener) eine Zahl ausgedruckt wird. Da eine Ausgabe bei dir etwa 10 ms dauert, hat das nur mehr vernachlässigbaren Einfluss (etwa 1%) auf die Gesamtausführungszeit. Da @BlackJack eine Ausführungszeit von 2 Minuten gemessen hat, kannst Du k=20000 wählen und erhälst dann etwa alle 1,2 Sekunden eine Ausgabe.
Haolong
User
Beiträge: 17
Registriert: Dienstag 26. Januar 2016, 14:49

Als ich mein Programm umgeschrieben hatte und so wie mein Kumpel nur die Primzahlen ausgegeben hatte, hat sich die Laufzeit des Programms jedoch nicht großartig verändert. (vielleicht 10 Minuten von 7,5 Stunden)

Ein entscheidender Punkt war das Abbrechen der Überprüfungen, nachdem erkannt wurde, dass die Zahl eine Primzahl ist. Das hat das Programm auf ca. Minuten runtergekürzt.

Wie schnell es bei meinem Kumpel gelaufen wäre, wenn er dasselbe gemacht hätte, weiß ich nicht.
Benutzeravatar
miracle173
User
Beiträge: 127
Registriert: Samstag 6. Februar 2016, 00:28

Hallo @Halong

Dann ist der print Befehl nicht der grösste Zeitfresser pro Iteration.
Ich habe nun beide Programme durchgesehen. Du schreibst "Ein entscheidender Punkt war das Abbrechen der Überprüfungen, nachdem erkannt wurde, dass die Zahl eine Primzahl ist". Ich denke, du meinst aber, "das Abbrechen der Überprüfungen, nachdem erkannt wurde, dass die Zahl keine Primzahl ist". Keine Primzahl ist sie, sobald sie durch eine Zahl aus der Liste teilbar ist. Tatsächlich kannst du aber auch erkennen, dass eine Zahl eine Primzahl ist, bevor du alle Zahlen der Liste durchprobiert hat. Eine Zahl n ist nähmlich dann schon eine Primzahl, wenn es keine Teiler kleiner als sqrt(n) hat. sqrt ist da die Wurzelfunktion , also entweder math.sqrt(n) oder n**.5 . Das verkürzt die Laufzeit noch weiter.
Und natürlich kannst du deinen Schleifen-range mit 3 beginnen und eine Schrittweite 2 nehmen, da du gerade Zahlen nicht überprüfen musst.

Das Javaprogramm hat einige Mängel. Double ist ein ungeeigneter Wert für i. Die Variable i ist eine ganze Zahl, man soll also int nehmen, und wenn das zu klein, was hier nicht der Fall ist, dann ist long eine Möglichkeit. Der Vergleich zahl==x ist auch äusserts schmerzaft, da hiere ein double mittles == verglichen wird. Das sollte nie geschehen. Sinnvollerweise sollte er einen modulus-Operator verwenden und nicht mit double herumspielen.

Intressant wäre es natürlich schon wenn ihr beide das gleichen Verfahren implementieren würdet, die sich wiederholdenden Printbefehle rausnehmt und dann die Laufzeit der Programme vergleicht.
DerTürke

Hi fallst du in der Lage bist Assembler Prozeduren ein zu binden, ich habe da leider keine Ahnung ob dies in Python möglich ist,
kannst du folgende Prozedur verwenden mit dieser Prozedur[codebox=asm file=Unbenannt.asm][/code] habe ich alle Primzahlen von 1-2.000.000 in weniger als 1 Sekunden ermitteln können.


[codebox=asm file=Unbenannt.asm];;; Checks if Value is PrimeValue
;;; Params: 1=Value
;;; RetValue = 0 false; 1 = true;
prcIsPrime PROC
PROLOG ; Makro ersetzen durch enter 0,0
push rdx

MOVE_PARAM r10, 1 ; Makro ersetzen durch mov r10, [rbp+8+1*8]
cmp r10, 01h
jz @NoPrime
cmp r10, 02h
jz @IsPrime
cmp r10, 03h
jz @IsPrime
cmp r10, 05h
jz @IsPrime
cmp r10, 07h
jz @IsPrime
mov r10, 2

@Weiter:
xor rdx, rdx
MOVE_PARAM rax, 1 ; ; Makro ersetzen durch mov rax, [rbp+8+1*8]
div r10
cmp rdx, 0
jz @NoPrime
inc r10
cmp r10, rax
jb @Weiter

@IsPrime:
mov rax, 01h ; IsPrime=true;
jmp @ExitProc

@NoPrime:
xor rax, rax

@ExitProc:
pop rdx
pop r10
EPILOG ; Makro ersetzen durch leave
ret
prcIsPrime ENDP[/code]
Zuletzt geändert von DerTürke am Mittwoch 11. Mai 2016, 23:44, insgesamt 1-mal geändert.
Grund: Quelltext in Code-Tags gesetzt.
DerTürke

Sorry nochmal im ersten script, war der push r10 verschwunden hätte natürlich gravierende folgen gehapt
[codebox=asm file=Unbenannt.asm];;; Checks if Value is PrimeValue
;;; Params: 1=Value
;;; RetValue = 0 false; 1 = true;
prcIsPrime PROC
PROLOG
push r10
push rdx

MOVE_PARAM r10, 1
cmp r10, 01h
jz @NoPrime
cmp r10, 02h
jz @IsPrime
cmp r10, 03h
jz @IsPrime
cmp r10, 05h
jz @IsPrime
cmp r10, 07h
jz @IsPrime
mov r10, 2

@Weiter:
xor rdx, rdx
MOVE_PARAM rax, 1
div r10
cmp rdx, 0
jz @NoPrime
inc r10
cmp r10, rax
jb @Weiter

@IsPrime:
mov rax, 01h ; IsPrime=true;
jmp @ExitProc

@NoPrime:
xor rax, rax

@ExitProc:
pop rdx
pop r10
EPILOG
ret
prcIsPrime ENDP


;;; Converts HexValue into string LATIN_BASIC
;;; Params: 1=HexValue
;;; RetValue = Pointer to string
prcHexToString PROC
PROLOG

push rcx
push rdx
push r8
push rdi

xor rcx, rcx
mov r8, 0ah
MOVE_PARAM rax, 1
@Weiter:
xor rdx, rdx
idiv r8
add rdx, 0030h
push rdx
inc rcx
cmp rax, 0
jnz @Weiter

lea rdi, offset asmPtrHexToStringValue
@Weiter2:
pop rdx
mov word ptr[rdi], dx
inc rdi
inc rdi
dec rcx
cmp rcx, 0
jnz @Weiter2
mov rax, offset asmPtrHexToStringValue

pop rdi
pop r8
pop rdx
pop rcx
EPILOG
ret
prcHexToString ENDP[/code]
Antworten