Seite 2 von 3
Re: Mal wieder was über BigInt
Verfasst: 24.05.2014 13:21
von Sauer-RAM
Ja ich habe mir schon gedacht, dass es mit Buffern oder Pointern funktionieren müsste.
Bei mir sah es dann aber nach
aus und ich hab da mehr geraten als gewusst (Buffer sind nicht so meins).
Vielen Dank Stargate für die Hilfe. Jetzt sollte (!) ich es allein hinbekommen.
Edit: Doch nicht

*Facepalm*
Wieso kann ich *Private nicht übergeben und es in der Prozedur als *Number behandeln? -.-'
Code: Alles auswählen
XIncludeFile "UnlimitedIntegerArithmetic.dll.pbi"
EnableExplicit
Define *Private.Z
Procedure CreateNumber(*Number.Z)
;Protected Number.Z
Protected n
Protected NumberString.s
If Not OpenCryptRandom()
ProcedureReturn 0
EndIf
For n = 1 To 10
NumberString.s + Str(CryptRandom(10))
Next
CloseCryptRandom()
Z_Number(*Number,NumberString)
ProcedureReturn *Number
EndProcedure
Procedure ISPrime(*Number.Z)
EndProcedure
CreateNumber(*Private)
Debug Z_String(*Private)
Re: Mal wieder was über BigInt
Verfasst: 24.05.2014 19:02
von Sicro
Versuche es mal so:
Code: Alles auswählen
*Private = CreateNumber(*Private)
Debug Z_String(*Private)
Die Speicher-Adresse ändert sich sicherlich beim Zuweisen einer Zahl, da die Daten dafür nicht mehr in den zuvor vom Betriebsystem reservierten Speicherbereich hineinpasst und deshalb ein größerer gefunden und reserviert werden musste. Führe mal diesen Code aus und du wirst es sehen:
Code: Alles auswählen
*a = AllocateMemory(10)
Debug *a
*a = ReAllocateMemory(*a, 200*1024) ; größer setzen, wenn die Adresse gleich bleibt
Debug *a
FreeMemory(*a)
In deiner Procedure gibst du ja bereits die Adresse als Rückgabewert an, aber verwendest diese nicht.
Re: Mal wieder was über BigInt
Verfasst: 24.05.2014 22:15
von STARGÅTE
Du verwechselt hier zwei sachen.
Meine Zahlen müssen als echte PB-Struktur initialisiert werden.
Diese Zahlen können dann aber nicht als Wert übergeben oder zurückgegeben werden, sondern nur als Adresse, daher in Procedure mit Übergabe als Pointer ansprechen.
Da die Zahlen mit PB-Strukturen initiallisiert werden und Arrays nutzen,
ändert sich die Adresse einer definierten Zahl nicht, egal wie groß sie wird!
Richtig wäre also:
Code: Alles auswählen
XIncludeFile "UnlimitedIntegerArithmetic.dll.pbi"
EnableExplicit
Define Private.Z
Procedure CreateNumber(*Number.Z)
;Protected Number.Z
Protected n
Protected NumberString.s
If Not OpenCryptRandom()
ProcedureReturn 0
EndIf
For n = 1 To 10
NumberString.s + Str(CryptRandom(10))
Next
CloseCryptRandom()
Z_Number(*Number,NumberString)
ProcedureReturn *Number
EndProcedure
Procedure ISPrime(*Number.Z)
EndProcedure
CreateNumber(Private)
Debug Z_String(Private)
Re: Mal wieder was über BigInt
Verfasst: 27.05.2014 14:45
von Sauer-RAM
Vielen Dank Stargate ^^.
Ich verstehe das mit den Buffern noch nicht so wirklich...
Aber eigentlich dürfte dein code doch garnicht funktionieren oder? Das "Protected Number.Z" ist ja auskommentiert. (Läuft aber trz)
Und wieso muss ich eine Prozedur, die einen Buffer erwartet, eine Struktur übergeben? Für mich ist das ziemlich.. Seltsam ^^
Re: Mal wieder was über BigInt
Verfasst: 27.05.2014 14:56
von STARGÅTE
Mein Include mutzt keine Buffer/Memorys, sondern die "normalen" Strukturen von PureBasic.
Strukturierte Variablen können und werden in PureBasic nur als Pointer an eine Prozedur übergeben.
Das heißt, ich ich übergeben der Prozedur nur eine Adresse, wo sie drin rumfuschen darf, wenn sie die Struktur ändern soll.
In der Prozedurdefinition wird diese Übergabe der Adresse nur das * gekennzeichnet.
Code: Alles auswählen
Structure Person
Vorname.s
Name.s
Alter.i
EndStructure
Procedure.s Information(*Person.Person) ; Die Prozedur erwartet eine Adresse mit der Struktur "Person"
ProcedureReturn *Person\Vorname+" "+*Person\Name+" ("+Str(*Person\Alter)+")"
EndProcedure
Procedure.s NewName(*Person.Person, Name.s) ; Die Prozedur erwartet eine Adresse mit der Struktur "Person"
*Person\Name = Name
EndProcedure
Define Ich.Person
Ich\Vorname = "Martin"
Ich\Name = "Guttmann"
Ich\Alter = 25
Debug Information(Ich) ; "Ich" kann nicht als Wert übergeben werden, wird also automatisch als Pointer übergeben (@Ich)
NewName(Ich, "Schmidt")
Debug Information(Ich)
Re: Mal wieder was über BigInt
Verfasst: 27.05.2014 15:08
von Sauer-RAM
Danke Stargate ^^.
Aber wenn ich einer Prozedur "Variable" übergebe, so erhält diese vermutlich den Interen Identifier der Variable.
Bei "*Variable" die Adresse und bei "@Variable" die Adresse des Pointers oder?
Müsse man dann nicht "CreateNumber" mit "*Private" aufrufen?
Re: Mal wieder was über BigInt
Verfasst: 27.05.2014 15:23
von STARGÅTE
"Name.Structure" hat nichts mit "*Name.Structure" zu tun.
Das sind zwei völlig verschiedene Definitionen und haben keine Verbindung zu einander.
- "Name.Structure" ist eine Variable und reserviert einen Speicherbereich mit der größe von "Structure" und allen nötigen dynamischen Elementen (Strings, Arrays, Listen)
- "*Name.Structure" ist ein Pointer und reserviert 4 bzw. 8 Byte für eine Speicheradresse (mehr nicht!).
Die Definition reserviert nicht den Speicher der Struktur selbst!
Die Definition der Struktur ermöglicht es die Speicheraddresse mit den Strukturfeldern zu lesen/schreiben.
Ein "@" vor einer Variable oder einem Pointer gibt die Speicheradresse dieses Objekts zurück.
- "@Name" gibt mir also die Speicheradresse, wo die Daten der Variable stehen.
- "@*Name" ist genauso möglich, gibt mir jedoch die Speicheradresse wo der Pointer gespeichert ist zurück.
Wird in PB "Test(Name)" aufgerufen und "Name" ist kein Standardtyp, so wird automatisch "Test(@Name)" übergeben.
Somit wird in der Prozedur eine Speicheradresse erwartet also "*Name"
Re: Mal wieder was über BigInt
Verfasst: 27.05.2014 16:03
von Sauer-RAM
Danke für deine Erläuterung, aber das war mir schon mehr oder weniger klar.
Die eigentliche Frage war: Warum schreibe ich Private in den *Number Pointer?
Dann steht doch der Inhalt von Private im Pointer von Number oder?
Re: Mal wieder was über BigInt
Verfasst: 27.05.2014 19:32
von Sauer-RAM
Ich präsentiere stolz, der Primzahltest mit Testcode. \^-^/ Ich kann kaum glauben, dass es wirklich funktioniert O_o. Vielen Danke Stargate :* :P.
Wenn jemand einen Fehler findet, oder Verbesserungsvorschläge hat, bitte ich darum.
Code: Alles auswählen
XIncludeFile "UnlimitedIntegerArithmetic.dll.pbi"
EnableExplicit
Define Private.Z
Define Jawohl
Procedure CreateNumber(*Number.Z)
;Protected Number.Z
Protected n
Protected NumberString.s
If Not OpenCryptRandom()
ProcedureReturn 0
EndIf
For n = 1 To 10
NumberString.s + Str(CryptRandom(10))
Next
CloseCryptRandom()
Z_Number(*Number,NumberString)
ProcedureReturn *Number
EndProcedure
Procedure ISPrime(*Number.Z,Accuracy.f)
;Pretest
Protected Number.Z
Protected.s NumberString = Z_String(*Number)
Protected.s LastNumber = Right(NumberString,1)
Protected NumberStringSize = Len(NumberString)
Protected Quersumme
Protected n
Protected A.Z
Protected ARandomMax.Z
Protected Zero.Z
Protected One.Z
Protected Two.Z
Protected Three.Z
Protected T.Z
Protected Alpha.Z
Protected TMod.Z
Protected k
Protected P.Z
Protected.b Prim = #False
Protected NumberMinusOne.Z
Protected PModN.Z
Protected kmax
kmax = Round(Log(1-Accuracy)/Log(1/4),#PB_Round_Up)
;Debug NumberString
;Debug LastNumber
If LastNumber = "2" ;Letzte Zahl 2
If NumberString = "2" ;Nur 2
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
EndIf
If LastNumber = "0" Or LastNumber = "4" Or LastNumber = "6" Or LastNumber = "8" ; Gerade
ProcedureReturn 0
EndIf
For n = 1 To NumberStringSize
Quersumme + Val(Mid(NumberString,n,1))
Next
If Mod(Quersumme,3) = 0 ;Quersumme durch 3 Teilbar ==> Keine Primzahl
If NumberString = "3"
ProcedureReturn 1 ;Nur 3
Else
ProcedureReturn 0
EndIf
EndIf
If LastNumber = "5" ;Durch 5 Teilbar (0 wird nicht berücksichtigt, da es schon bei "gerade" dabei ist)
If NumberString = "5"
ProcedureReturn 1 ;Nur 5
Else
ProcedureReturn 0
EndIf
EndIf
;Eigentlicher Test
Z_Set(Zero,0)
Z_Set(One,1)
Z_Set(Two,2)
Z_String(Two)
Z_Set(Three,3)
Z_Copy(ARandomMax,*Number)
Z_Copy(T,*Number)
Z_subtract(ARandomMax,Three)
Z_Subtract(T,One)
Z_Copy(NumberMinusOne,*Number)
Z_Subtract(NumberMinusOne,One)
For k = 0 To kmax
Z_Random(A,ARandomMax) ;2 <= A <= Number - 1
Z_Add(A,Two)
Z_Zero(Alpha)
Z_copy(Tmod,T)
Z_Modulo(Tmod,Two)
While Z_Compare(Tmod,Zero) = #Z_Equal
Z_Divide(T,Two)
Z_add(Alpha,One)
Z_Copy(Tmod,T)
Z_Modulo(Tmod,Two)
Wend
Z_Copy(P,A)
Z_PowerModulo(P,T,*Number)
Prim = #False
Z_subtract(Alpha,One)
If Z_Compare(P,NumberMinusOne) = #Z_Equal Or Z_Compare(P,One) = #Z_Equal
Prim = #True
EndIf
While Prim = #False And Z_Compare(Alpha,Zero) = #Z_Greater And Z_Compare(P,One) = #Z_Greater
Z_copy(PModN,P)
Z_modulo(P,*Number)
Z_Multiply(P,PModN)
Z_subtract(Alpha,One)
If Z_Compare(P,NumberMinusOne) = #Z_Equal
Prim = #True
EndIf
Wend
If Prim = #False
ProcedureReturn 0
EndIf
Next
ProcedureReturn 1
EndProcedure
Repeat
CreateNumber(Private)
Jawohl = ISPrime(Private,0.999999)
Debug "Prime = " + Str(Jawohl)
Debug "Number = " + Z_String(Private)
Until Jawohl = 1
Re: Mal wieder was über BigInt
Verfasst: 27.05.2014 19:48
von Sauer-RAM
Ok.. Da ist ein Bug drinn..
22801763489 wird nicht als Primzahl erkannt, aber ich arbeite drann. -.-'
Edit: Hier ist der benutzte Algorithmus:
http://primzahlen.zeta24.com/de/miller_ ... hltest.php
Vielen Dank für die Hilfe