Mal wieder was über BigInt

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Sauer-RAM
Beiträge: 326
Registriert: 13.04.2009 16:22
Computerausstattung: Lenovo ThinkPad X230t Convertible
Wohnort: Haslach i. K.

Re: Mal wieder was über BigInt

Beitrag 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

Code: Alles auswählen

*Number = CreateNumber()
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 :oops: *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)
"Bildung kommt vom Bildschirm und nicht vom Buch, sonst hieße es ja Buchung."
Dieter Hildebrandt
"Bildung ist Das, was übrig bleibt, wenn man alles was man in der Schule gelernt hat, vergisst. "
Albert Einstein
Benutzeravatar
Sicro
Beiträge: 963
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: Mal wieder was über BigInt

Beitrag 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.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Mal wieder was über BigInt

Beitrag von STARGÅTE »

Du verwechselt hier zwei sachen.

Meine Zahlen müssen als echte PB-Struktur initialisiert werden.

Code: Alles auswählen

Define Number.Z ; oder Protected oder Global usw.
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.

Code: Alles auswählen

Procedure Test(*Private.Z)
EndProcedure

Test(Number)
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)
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Sauer-RAM
Beiträge: 326
Registriert: 13.04.2009 16:22
Computerausstattung: Lenovo ThinkPad X230t Convertible
Wohnort: Haslach i. K.

Re: Mal wieder was über BigInt

Beitrag 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 ^^
"Bildung kommt vom Bildschirm und nicht vom Buch, sonst hieße es ja Buchung."
Dieter Hildebrandt
"Bildung ist Das, was übrig bleibt, wenn man alles was man in der Schule gelernt hat, vergisst. "
Albert Einstein
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Mal wieder was über BigInt

Beitrag 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)
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Sauer-RAM
Beiträge: 326
Registriert: 13.04.2009 16:22
Computerausstattung: Lenovo ThinkPad X230t Convertible
Wohnort: Haslach i. K.

Re: Mal wieder was über BigInt

Beitrag 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?
"Bildung kommt vom Bildschirm und nicht vom Buch, sonst hieße es ja Buchung."
Dieter Hildebrandt
"Bildung ist Das, was übrig bleibt, wenn man alles was man in der Schule gelernt hat, vergisst. "
Albert Einstein
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Mal wieder was über BigInt

Beitrag 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"
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Sauer-RAM
Beiträge: 326
Registriert: 13.04.2009 16:22
Computerausstattung: Lenovo ThinkPad X230t Convertible
Wohnort: Haslach i. K.

Re: Mal wieder was über BigInt

Beitrag 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?
"Bildung kommt vom Bildschirm und nicht vom Buch, sonst hieße es ja Buchung."
Dieter Hildebrandt
"Bildung ist Das, was übrig bleibt, wenn man alles was man in der Schule gelernt hat, vergisst. "
Albert Einstein
Benutzeravatar
Sauer-RAM
Beiträge: 326
Registriert: 13.04.2009 16:22
Computerausstattung: Lenovo ThinkPad X230t Convertible
Wohnort: Haslach i. K.

Re: Mal wieder was über BigInt

Beitrag 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
Zuletzt geändert von Sauer-RAM am 27.05.2014 21:55, insgesamt 1-mal geändert.
"Bildung kommt vom Bildschirm und nicht vom Buch, sonst hieße es ja Buchung."
Dieter Hildebrandt
"Bildung ist Das, was übrig bleibt, wenn man alles was man in der Schule gelernt hat, vergisst. "
Albert Einstein
Benutzeravatar
Sauer-RAM
Beiträge: 326
Registriert: 13.04.2009 16:22
Computerausstattung: Lenovo ThinkPad X230t Convertible
Wohnort: Haslach i. K.

Re: Mal wieder was über BigInt

Beitrag 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
"Bildung kommt vom Bildschirm und nicht vom Buch, sonst hieße es ja Buchung."
Dieter Hildebrandt
"Bildung ist Das, was übrig bleibt, wenn man alles was man in der Schule gelernt hat, vergisst. "
Albert Einstein
Antworten