Wurzel aus 2

Anfängerfragen zum Programmieren mit PureBasic.
Pandorra
Beiträge: 124
Registriert: 10.02.2007 12:15

Wurzel aus 2

Beitrag von Pandorra »

hallo,
ich will wie der Threadname schon sagt die Wurzel aus 2 berechnen.
Natürlich nicht ganz genau aber mindestens schon bis zu der 50 Stelle.
Nun ist das Problem das PB ab der 16 Stelle fehler einbaut (bei der Wurzel und bei der Zahl).
Nach der 82 Stelle streikt das Programm ganz und beendet sich nicht.
Deswegen ist 82 auch das Limit.

Gibt es eine Möglichkeit bis zu 50 Stelle zu kommen ohne das PB sich verrechnet?

Hier der Code:

Code: Alles auswählen

Wurzel.d = 200
Zahl.d = 14
Mal.d = 1
Stellen = 2

Repeat

   Stellen+1
   Zahl*10
   Wurzel*100
   
   Repeat
     Zahl+1
     
     If Zahl*Zahl > Wurzel
        Zahl-1
        Break
     EndIf
     
     If Zahl*Zahl = Wurzel
        Break
     EndIf
     
   ForEver
   
Until Zahl*Zahl = Wurzel Or Stellen = 82

Debug Zahl

Danke für die Antworten schon mal im vorraus.




Mit freundlichen Grüßen Pandorra
Benutze PB v 4.40 Beta 3
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

eine ähliche Frage hatten wir schon mal,

NEIN

du rechnest in deinem Code mit Doubles und die haben nur eine bestimmt genauigkeit die man nicht verbessern kann.

Wenn du es noch genauer willst, musst du dir einen eigene Typ schreiben der zB mit Strings arbeitet ...
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
Andesdaf
Moderator
Beiträge: 2673
Registriert: 15.06.2008 18:22
Wohnort: Dresden

Beitrag von Andesdaf »

> Gibt es eine Möglichkeit bis zu 50 Stelle zu kommen ohne das PB sich verrechnet?
Nein. Eine Doublezahl ist nur 16 Stellen genau. Es gibt noch die Möglichkeit mit
Longdouble zu rechnen, Longdouble rechnet einige Stellen genauer, aber
nicht 50.
Win11 x64 | PB 6.20
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Beitrag von DarkDragon »

Andesdaf hat geschrieben:> Gibt es eine Möglichkeit bis zu 50 Stelle zu kommen ohne das PB sich verrechnet?
Nein. Eine Doublezahl ist nur 16 Stellen genau.
Falsche angabe! Es kommt darauf an was für ein Wert gespeichert wird. Beispielsweise kann man 0.1 nicht eindeutig durch 2er Potenzen ausdrücken.
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Pandorra
Beiträge: 124
Registriert: 10.02.2007 12:15

Beitrag von Pandorra »

danke für eure Hilfe.
Ich werde es dann weiter versuchen.
Benutze PB v 4.40 Beta 3
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

also, um es ganz präzise zu sagen, eine Double ist auf 56 wertebit genau,
bzw. auf 56 Binärstellen.


@topic

gabs da nicht mal eine Lib, die mit stringzahlen rechnet?
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Beitrag von DarkDragon »

Kaeru Gaman hat geschrieben:also, um es ganz präzise zu sagen, eine Double ist auf 56 wertebit genau,
bzw. auf 56 Binärstellen.


@topic

gabs da nicht mal eine Lib, die mit stringzahlen rechnet?
Bignum - war in PBOSL, würde wohl auch wieder reinkommen.
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Pandorra
Beiträge: 124
Registriert: 10.02.2007 12:15

Beitrag von Pandorra »

hab es mit einem Code von Little John geschaft.
http://www.purebasic.fr/german/viewtopic.php?t=17119

Ich würde euch gerne meinen Verbesserten Code zeigen da der PC aber gerade die Wurzel von 2 auf 3000 Stellen nach dem Komma rechnet lagt es.
Deswegen hier ohne einrücken:

Da ich zu faul bin auch die Division von Little John zu nehmen habe ich es so gelassen das er es ohne Komma macht.
Muss man sich ebend denken.
Werde es evtl. später einen Code posten wo das Komma zum Schluss automatisch eingefügt wird.

Code: Alles auswählen

Procedure.s Zeros (count) 
   Protected ret.s, i 

   ret = "" 
   For i = 1 To count 
      ret + "0" 
   Next 
   ProcedureReturn ret 
EndProcedure 

Procedure.s LTrimZeros (str.s) 
   ; -- entfernt führende Nullen 
   Protected p 

   p = 1 
   While p < Len(str) And Mid(str,p,1) = "0" 
      p + 1 
   Wend 
   ProcedureReturn Mid(str, p) 
EndProcedure 

#Signs = "+-" 
#SignPos = 0 
#SignNeg = 2 

Procedure.s Prepare (x.s, *y.Integer) 
   ; -- entfernt ein vorhandenes Vorzeichen sowie führende Nullen 
   ; in : x repräsentiert eine ganze Zahl, 
   ;      das erste Zeichen kann "+" oder "-" sein 
   ; out: *y\i        : Vorzeichen als Zahl (#SignPos oder #SignNeg) 
   ;      Rückgabewert: String ohne Vorzeichen und führende Nullen 

   *y\i = FindString(#Signs, Left(x, 1), 1) 
   If *y\i > 0 
      x = Mid(x, 2) 
   EndIf 
   *y\i & 2 
   ProcedureReturn LTrimZeros(x) 
EndProcedure 

Procedure.i AbsCmp (a.s, b.s) 
   ; -- vergleicht die Größen von a und b 
   ; in : a und b repräsentieren ganze Zahlen ohne Vorzeichen 
   ; out: -1: a < b 
   ;       0: a = b 
   ;      +1: a > b 

   If Len(a) < Len(b) 
      ProcedureReturn -1 
   ElseIf Len(a) > Len(b) 
      ProcedureReturn 1 
   ElseIf a < b 
      ProcedureReturn -1 
   ElseIf a > b 
      ProcedureReturn 1 
   Else 
      ProcedureReturn 0 
   EndIf 
EndProcedure 

Procedure.s AbsAdd (a.s, b.s) 
   ; -- ahmt die schriftliche Addition nach 
   ; in : a und b repräsentieren ganze Zahlen ohne Vorzeichen 
   ; out: a + b 
   Protected ret.s 
   Protected n, d, i, u, d_a, d_b, r 

   n = Len(a) 
   d = n - Len(b) 
   If d > 0 
      b = Zeros(d) + b 
   ElseIf d < 0 
      n = Len(b) 
      a = Zeros(-d) + a 
   EndIf 

   u = 0 
   ret = "" 
   For i = n To 1 Step -1 
      d_a = Val(Mid(a, i, 1)) 
      d_b = Val(Mid(b, i, 1)) 
      r = d_a + d_b + u 
      u = Int(r/10) 
      r = r % 10 
      ret = Str(r) + ret 
   Next 
   If u > 0 
      ret = Str(u) + ret 
   EndIf 
   ProcedureReturn ret 
EndProcedure 


Procedure.s AbsSub (a.s, b.s) 
   ; -- ahmt die schriftliche Subtraktion nach 
   ; in : a und b repräsentieren ganze Zahlen ohne Vorzeichen, 
   ;      a muss >= b sein 
   ; out: a - b 
   Protected ret.s 
   Protected n, d, i, u, d_a, d_b, r 

   n = Len(a) 
   d = n - Len(b) 
   If d > 0 
      b = Zeros(d) + b 
   ElseIf d < 0 
      n = Len(b) 
      a = Zeros(-d) + a 
   EndIf 

   u = 0 
   ret = "" 
   For i = n To 1 Step -1 
      d_a = Val(Mid(a, i, 1)) 
      d_b = Val(Mid(b, i, 1)) 
      r = d_a - d_b - u 
      If r < 0 
         r + 10 
         u = 1 
      Else 
         u = 0 
      EndIf 
      ret = Str(r) + ret 
   Next 
   ProcedureReturn LTrimZeros(ret) 
EndProcedure 

Procedure.s AbsMul(a.s, b.s) 
   ; -- ahmt die schriftliche Multiplikation nach 
   ; in : a und b repräsentieren ganze Zahlen ohne Vorzeichen 
   ; out: a * b 
   Protected x.s, ret.s 
   Protected p_a, p_b, u, d_a, d_b, r 

   ret = "" 
   For p_b = 1 To Len(b) 
      d_b = Val(Mid(b, p_b, 1)) 
      u = 0 
      x = "" 
      For p_a = Len(a) To 1 Step -1 
         d_a = Val(Mid(a, p_a, 1)) 
         r = d_a * d_b + u 
         u = Int(r/10) 
         r = r % 10 
         x = Str(r) + x 
      Next 
      If u > 0 
         x = Str(u) + x 
      EndIf 
      ret = AbsAdd(ret + "0", x) 
   Next 
   ProcedureReturn ret 
EndProcedure 

Global Wurzel.s = "2"
Global Zahl.s = ""
Global Mal.d = 1
Global Stellen.d = 0
Global maxStellen.d = 800

OpenConsole()

Global Zeitspanne
Global MaxZeitspanne = 20000
Global Start


PrintN("Wurzelberechnung von 2")
PrintN("Die Zahl angeben dessen Wurzel berechnet werden soll (ohne Eingabe ist es 2)")
Input.s = Input()
If Not Input = ""
Wurzel = Input
EndIf
PrintN("Ziehe die Wurzel von " + Wurzel)

PrintN("Anzahl an Stellen nach dem Komma angeben( bei keiner Angabe 800)")
Input.s = Input()
If Not Input = ""
maxStellen = Val(Input)
EndIf
PrintN("Suche bis zu " + Str(maxStellen) + " Stellen nach dem Komma")

Repeat

   Stellen+1
   
   
   Repeat
     Zahl = AbsAdd (Zahl,"1")
     
     If AbsCmp (AbsMul(Zahl,Zahl),Wurzel) = 1
        Zahl = AbsSub (Zahl,"1")
        Break
     EndIf
     
     If AbsCmp (AbsMul(Zahl,Zahl),Wurzel) = 0
        Break 2
     EndIf
   ForEver


If Zeitspanne => MaxZeitspanne
Start = ElapsedMilliseconds()
PrintN("Stellen nach dem Komma " + Str(Stellen))
PrintN("Zahl " + Zahl)
PrintN("Bei " + StrD((Stellen/maxStellen)*100,2)+"%")
If CreateFile(0, "Wurzel.txt")
  WriteStringN(0, "(Nicht ernst nehmen ist) " + Wurzel)
  WriteStringN(0, Str(Stellen) + " Stellen nach dem Komma")
  WriteStringN(0, Zahl)
  CloseFile(0)
EndIf
EndIf

Zeitspanne = ElapsedMilliseconds() - Start
   
 
   Zahl = AbsMul(Zahl,"10")
   Wurzel = AbsMul(Wurzel,"100")
   
Until Stellen = maxStellen


PrintN("Stellen nach dem Komma " + Str(Stellen))
PrintN("Zahl " + Zahl)
PrintN("Bei " + StrD((Stellen/maxStellen)*100,2)+"%")

If CreateFile(0, "Wurzel.txt")
  WriteStringN(0, "(Nicht ernst nehmen ist) " + Wurzel)
  WriteStringN(0, Str(Stellen) + " Stellen nach dem Komma")
  WriteStringN(0, Zahl)
  CloseFile(0)
  If Stellen > 1
  MessageRequester("Wurzelberechnung Erfolgreich", "Fertig "+Str(Stellen)+" Stellen nach dem Komma", 0)
  ElseIf Stellen = 1
  MessageRequester("Wurzelberechnung Erfolgreich", "Fertig "+Str(Stellen)+" Stelle nach dem Komma", 0)
  EndIf
Else
  MessageRequester("PureBasic", "Error: can't write the file (Datas will be removed)", 0)
  End
EndIf

End


hoffe das es so gut.
Oh mein Gott lagt das.

Mit freundlichen Grüßen Pandorra
Zuletzt geändert von Pandorra am 12.02.2009 22:28, insgesamt 2-mal geändert.
Benutze PB v 4.40 Beta 3
Little John

Beitrag von Little John »

Kaeru Gaman hat geschrieben:gabs da nicht mal eine Lib, die mit stringzahlen rechnet?
Hiermit sollte es gehen.

Gruß, Little John

//edit: Uups, zu langsam. ;-)
Zuletzt geändert von Little John am 12.02.2009 22:25, insgesamt 1-mal geändert.
Pandorra
Beiträge: 124
Registriert: 10.02.2007 12:15

Beitrag von Pandorra »

war schneller :lol:
Suche war mein Freund :D
Aber danke für die Bemühungen Little John und auch für deinen Code...




pandorra
Benutze PB v 4.40 Beta 3
Antworten