isSchnapszahl() » auch für negative Zahlen

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

isSchnapszahl() » auch für negative Zahlen

Beitrag von AND51 »

Hallo!

Mir war langweilig, und endlich ist mir was eingefallen: isSchnapszahl()
Vielleicht kann man es der ein oder andere ja doch noch gebrauchen.
Die Prozedur funktioniert übrigens auch prima mit negativen Zahlen!

Code: Alles auswählen

Procedure isSchnapszahl(zahl.l) ; AND51/Jan-2008
	Protected ziffer.l=zahl%10
	If zahl > 10 Or zahl < -10
		While zahl
			If zahl%10 <> ziffer
				ProcedureReturn 0
			EndIf
			zahl/10
		Wend
		ProcedureReturn 1
	EndIf
EndProcedure

Debug isSchnapszahl(-222222222)
Wie so oft bin ich sehr an performanteren Codes interessiert, wem es also in den Fingern kribbelt... :allright:
Die üblichen Mitmachregeln:
-performant & galant
-Unicodesupport :mrgreen:
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8808
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 »

Weiß nicht, ob das schneller ist, aber ich habe mal an MODs gespart. Dafür
läuft aber die Schleife alle Ziffern durch.

Code: Alles auswählen

Procedure isSchnapszahl2(zahl.l)
  Protected ziffer.l, zahl2.l
  If zahl < 0 : zahl = -zahl : EndIf
  If zahl < 10 : ProcedureReturn #False : EndIf
  ziffer = zahl % 10
  While zahl2 < zahl : zahl2 * 10 + ziffer : Wend
  ProcedureReturn (Not (zahl2 ! zahl))
EndProcedure

Debug isSchnapszahl2(232)
Debug isSchnapszahl2(4444)
Aber der Geschwindigkeitsvorteil macht sich bei den paar Ziffern, die ein
Long aufnehmen kann, wohl kaum bemerkbar.

Dann lieber mit Strings. :mrgreen:

Code: Alles auswählen

Procedure isSchnapszahl3(*c.Character)
  Protected *c2.Character = *c
  While *c\c
    If *c\c ! *c2\c : ProcedureReturn #False : EndIf
    *c + SizeOf(Character)
  Wend
  ProcedureReturn ((*c - *c2 - SizeOf(Character)) * *c2\c) And 1
EndProcedure

Debug isSchnapszahl3(@"232")
Debug isSchnapszahl3(@"4")
Debug isSchnapszahl3(@"44")
Debug isSchnapszahl3(@"")
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

freak hatte letztens gesagt, dass ein MOD auch nur ein DIV ist,
lediglich das andere rückgaberegister wird abgefragt.
sollte also wesentlich performanter sein, als die algorithmen von früher.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8808
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 »

@Kaeru Gaman:
Habs grad gesehen.

Cool!

Code: Alles auswählen

; a.l = 4
  MOV    dword [v_a],4
; b.l = 3
  MOV    dword [v_b],3
; c.l = a % b
  MOV    ebx,dword [v_a] ;markiert
  MOV    eax,ebx ;markiert
  CDQ
  IDIV   dword [v_b]
  MOV    ebx,edx
  MOV    dword [v_c],ebx
Warum der Compiler aus den beiden markierten Zeilen allerdings nicht
eine macht, weiß ich nicht.

Code: Alles auswählen

MOV    Eax,dword [v_a]
Zuletzt geändert von NicTheQuick am 11.01.2008 16:28, insgesamt 1-mal geändert.
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

@ NtQ:
Hey cool!
Geschickt, du schnappst dir die letzte Ziffer und reihst diese so oft hintereinander, wie die Originalzahl Ziffern hat!

So etwas ähnlcihes habe ich vorher auch versucht: Ich habe die Länge der Zahl (mit der MOD-Methode) und die Quersumme gebildet und wollte daraus was basteln... Hat aber nicht ganz so geklappt und so bin ich bei meiner Methode gelandet.
Ich habe auch schon daran gedacht, mit bool'schen Ausdrücken zu arbeiten, aber damit wäre ich lieber vorsichtig; zumindest, bis man das "offiziell" kann.

@ Kaeru Gaman:
Danke für diese Info! hatte mich schon gefragt, wie Mod eigentlich arbeitet...


@ NtQ:
Deine prozedur ist deutlisch schneller!
Bei 1<<24 (16,7 Mio.) Schleifendurchläufen braucht deine Prozedur (bei mir) ziemlich genau 1 Sekunde. Meine Prozedur braucht knapp über 4 Sekunden.
Aber ich gebe nicht auf! :lol:
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

@ NtQ:
Ich habe einen Bug gefunden, deine Prozedur versagt bei -10.
Die While Schleife kann nicht verlassen werden. Dies liegt daran, dass du die Ziffer 0 schnappst und diese dann mit 10 multiplizierst (ergibt immer null). Die Bedingung bis die generierte Zahl 'zahl2' größer als 'zahl' ist, wird also nie erfüllt.
Deshalb ist vermutlich dieser Bug bei dir bei allen Zahlen, die auf null enden.
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8808
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 »

Na dann muss man die WhileSchleife etwas ändern:

Code: Alles auswählen

While zahl2 < zahl And ziffer : zahl2 * 10 + ziffer : Wend
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Beitrag von Xaby »

Kaeru Gaman hat geschrieben:freak hatte letztens gesagt, dass ein MOD auch nur ein DIV ist
Ein DOM ist auch nur ein SUB :mrgreen: :allright:
Kinder an die Macht http://scratch.mit.edu/
Benutzeravatar
TomS
Beiträge: 1508
Registriert: 23.12.2005 12:41
Wohnort: München

Beitrag von TomS »

Ein spanisches Dorf ist auch nur ein Bahnhof :roll:
Sorry, ich kapier gar nix. Aber interessieren würd's mich schon. Wo kommt denn in dem Code von da oben MOD oder DIV vor und was soll das überhaupt sein?
Benutzeravatar
Thorium
Beiträge: 1722
Registriert: 12.06.2005 11:15
Wohnort: Germany
Kontaktdaten:

Beitrag von Thorium »

NicTheQuick hat geschrieben:

Code: Alles auswählen

; a.l = 4
  MOV    dword [v_a],4
; b.l = 3
  MOV    dword [v_b],3
; c.l = a % b
  MOV    ebx,dword [v_a] ;markiert
  MOV    eax,ebx ;markiert
  CDQ
  IDIV   dword [v_b]
  MOV    ebx,edx
  MOV    dword [v_c],ebx
Warum der Compiler aus den beiden markierten Zeilen allerdings nicht
eine macht, weiß ich nicht.

Code: Alles auswählen

MOV    Eax,dword [v_a]
Ist zwar Offtopic aber es passt grad so schön.
Von wegen Compileroptimierung und so. Bin heute über einen Code, den der VS C++ Compiler gebaut hat gestolpert, wo ich auch schmunzeln musste.

Code: Alles auswählen

MOV EBP,ESP
PUSH ECX
MOV DWORD PTR SS:[EBP-4],ECX
MOV ECX,DWORD PTR SS:[EBP-4]
:lol:
Zu mir kommen behinderte Delphine um mit mir zu schwimmen.

Wir fordern mehr Aufmerksamkeit für umfallende Reissäcke! Bild
Antworten