Quersumme(zahl.q)

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Quersumme(zahl.q)

Beitrag von AND51 »

Hallo!

Hier mal (m)eine Prozedur, die die Quersumme einer Ganzzahl ermittelt:

Code: Alles auswählen

Procedure Quersumme(zahl.q)
	If zahl < 0
		zahl=-zahl
	EndIf
	Protected string.s=StrQ(zahl), *zahl.Character=@string, result.l
	While *zahl\c
		result+PeekC(*zahl)-48
		*zahl+SizeOf(Character)
	Wend
	ProcedureReturn result
EndProcedure

Debug quersumme(-123)

Vielleicht könnt ihr mir ja helfen, diese Prozedur zu verbessern? Ich würde gern auf die einzelnen Ziffern der Zahl zugreifen können, ohne die Zahl vorher in einen String konvertieren zu müssen. Außerdem muss es doch bestimmt eine elegantere Lösung dafür geben, wenn die Zahl negativ ist? Vielleicht irgendeine Bit-Operation?
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Ich würd's z.B. so machen:

Code: Alles auswählen

Procedure Quersumme(zahl.q)
  Protected Result.l
  
  If zahl < 0 : zahl * -1 : EndIf
  While zahl
    Result + zahl % 10
    zahl / 10
  Wend
  
  ProcedureReturn Result
EndProcedure

Debug Quersumme(-123)
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Irgendwie hatte ich schon son eine Ahnung, dass du dich meldest... <)
Danke für deine Idee! Da hätte ich eigentlich auch drauf kommen können mit Modulo...

Was jetzt performanter ist, ließe sich sicher ermitteln (grad keine Lust).

hab noch ne Frage: Die Art und Weise, wie wir beide negative Zahlen in positive Zahlen umwandeln (if zahl < 0), welche Art ist schneller? Meine oder deine?

Ich habe mir gedacht, dass eine Multiplikation mit -1 vielleicht langsamer sein könnte, als wenn man -(-zahl) rechnet. Ist nur ne Vermutung, klärt mich auf! :allright:
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
hardfalcon
Beiträge: 3447
Registriert: 29.08.2004 20:46

Beitrag von hardfalcon »

Ob du eine Rechenoperation mit einer positiven oder einer negativen Zahl ausführst, geschwindigkeitsmässig völlig egal, weil die CPU so oder so mit 32Bit rechnet, egal ob da jetzt ein Bit ne 0 oder ne 1 ist... :wink:

NickTheQuicks Variante ist aber wesentlich schneller als deine, das kann ich dir auch ohne Benchmark sagen. String-Umwandlungen sind so ziemlich das langsamste, was man mit zahlen am PC machen kann... <)
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Aber wenn man so vorgeht, wie ich, ist es nicht egal, ob man mit positiven oder negativen Zahlen rechnet, weil:
Das Minuszeichen - hat den ASCII-Wert 45; ich subtrahiere generell 48, weil ich davon ausgehe, nur Ziffern und keine Sonderzeichen vorzufinden.

Ein Minuszeichen verfälscht also mein Ergebnis, wenn ich keine Überprüfung drin hab.

> NickTheQuicks Variante ist aber wesentlich schneller als deine
Stimmt, das kann ich mir jetzt auch denken.

Was ich aber meinte war dies:
a) zahl = zahl * -1
b) zahl = -zahl
Welche Variante ist hier schneller?
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Es gibt es einen ASM-Befehl, der eine Zahl negieren kann:

Code: Alles auswählen

a.l = 4
!NEG [v_a]
Debug a
Der sollte am schnellsten sein. Es kann sogar sein, dass 'a = -a' von PB in
diesen Code umgewandelt wird. Damit wäre deine Variante schneller.

Ansonsten ist eine Multiplikation genauso schnell wie eine Addition, weil es
jeweils nur ein Befehl ist. Allerdings braucht man eben ein Register mehr,
soviel ich weiß. Ich kenne mich mit ASM ja eigentlich gar nicht aus.
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Danke für den Befehl, NtQ!

> Es kann sogar sein, dass 'a = -a' von PB in diesen Code umgewandelt wird. Damit wäre deine Variante schneller.
Kann das jemand bestätigen?

> Ich kenne mich mit ASM ja eigentlich gar nicht aus.
lol me 2 <)

Gibt es denn einen Befehl, der Zahlen nur bei Bedarf negiert, also soetwas wie Abs() für große Zahlen?
das meinte ich, als ich den Gedanken äußerte, vielleicht ginge das ja mit einer Bit-Operation, wie es in der Hilfe steht:

Code: Alles auswählen

Define a.b = -64
Debug a & 255 ; ergibt 192
Gibt es soetwas für Quads? Beziehungsweise würde in diesem Codebeispiel jede beliebige Zahl automatisch positiv werden oder bleiben, wenn ich ein &255 draufknalle?
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Zahl = -Zahl setzt PB mit NEG um, für die (64-Bit!)Multiplikation muss PB eine eigene Routine aufrufen. Da PB keinen NEG-Befehl hat (wenn ich das richtig sehe) kann man aber mal folgendes probieren:

Code: Alles auswählen

Zahl = -123
Zahl = ~Zahl + 1
Debug Zahl
NEG ist ja NOT + 1.

Gruss
Helle
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Hey helle!
Vielen Dank für deine Info!
Ist NEG immer NOT+1 ? Also egal in welche Richtung und egal mit welcher Zahl?
Außer null...

Hm... mit der Null hat man schon wieder nen Sonderfall...
Vielleicht sollte ich aufhören einen Universalbefehl für alles zu suchen, obwohls schon praktisch wäre.
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Null ist kein Sonderfall:

Code: Alles auswählen

Zahl = 0
Zahl = ~Zahl + 1
Debug Zahl
Antworten