Seite 1 von 3

Verfasst: 14.08.2006 01:17
von Kaeru Gaman

Code: Alles auswählen

Procedure test() 
   If ExamineDirectory(0, "c:\", "*.*") 
      While NextDirectoryEntry(0) 
         a.q = DirectoryEntrySize(0) 
    Debug a 
      Wend 
   EndIf 
EndProcedure 

test() 
der rückgabewert ist keine float.
mit long gehts auch ohne fehler, aber dann bekommt man bei sehr großen dateien (z.b. dem virtuellen speicher) ein falsches ergebnis.

ok,
1. es steht nicht in der Help
2. die art der fehlermeldung ist seltsam
ich tippe auf irgendein stack-problem, das durch den Rücksprung ausgelöst wird.

ich selber hab da nich so die ahnung von.
evtl. kann ja mal jemand an die version ohne Proc noch ne stack-operation dranhängen, um meine theorie zu überprüfen.

wahrscheinlich ift noch keiner auf das problem gestoßen,
weil man eigentlich nicht auf die idee kommt,
den rückgabewert in ne float zu packen.

Verfasst: 14.08.2006 03:54
von PureLust
Wie Kaeru schon angedeutet hat, wird es wohl tatsächlich an irgendeiner Unverträglichkeit des Rückgabewertes liegen (wird vemutlich ein 8 Byte Quad-Wert sein).

Denn auch mit einem 8 Byte Double-Wert funktioniert es problemlos.
Und auch wenn man eine explizite Umwandlung (durch einfügen eines Operators) druchführt, erhält man keinen Fehler.

Code: Alles auswählen

Procedure TestDouble() 
   If ExamineDirectory(0, "c:\", "*.*") 
      While NextDirectoryEntry(0) 
         a.d = DirectoryEntrySize(0)
    Debug a 
      Wend 
   EndIf 
EndProcedure

Procedure TestFloat() 
   If ExamineDirectory(0, "c:\", "*.*") 
      While NextDirectoryEntry(0) 
         a.f = DirectoryEntrySize(0)+0
    Debug a 
      Wend 
   EndIf 
EndProcedure

Debug TestDouble()
Debug TestFloat()

Verfasst: 14.08.2006 23:41
von Kaeru Gaman
Kaeru Gaman hat geschrieben:mit long gehts auch ohne fehler, aber dann bekommt man bei sehr großen dateien (z.b. dem virtuellen speicher) ein falsches ergebnis.
;)

Verfasst: 14.08.2006 23:58
von jear
Schlage mich auch gerade mit der Geschichte rum. Irgendwas geht da fürchterlich schief mit den Rückgabewerten, wenn irgendwelche Grenzen überschritten werden.
Allerdings sollten Floats, Doubles und Quads bequem die Zahl von 8.172.071.838 Bytes aufnehmen können, die mein Programmverzeichnis laut Windows groß ist.

Code: Alles auswählen

Structure GetNum
  Files.l
  Dirs.l
EndStructure

;/ rekursive Ermittlung der Gesamtgröße der Dateien ( in Bytes)
;/ in einem Verzeichnisbaum über eine Quad-Variable
Procedure.q DirTreeSize_q(id.l, Directory.s, *Num.GetNum) 
  Protected Name.s
  Protected Size.q, Entry.l
  If ExamineDirectory(id, Directory, "*.*") 
    While NextDirectoryEntry(id) 
      Entry = DirectoryEntryType(id)
      If Entry = #PB_DirectoryEntry_File 
        Size + DirectoryEntrySize(id)
        *Num\Files + 1
      ElseIf Entry = #PB_DirectoryEntry_Directory
        Name = DirectoryEntryName(id) ; Debug Name 
        If Name <> ".." And Name <> "." 
          Size + DirTreeSize_q(id + 1, Directory + Name + "\", *Num.GetNum) 
          *Num\Dirs + 1
        EndIf 
      EndIf 
    Wend
  EndIf 
  ProcedureReturn Size 
EndProcedure

;/ rekursive Ermittlung der Gesamtgröße der Dateien (in Bytes)
;/ in einem Verzeichnisbaum über eine Float-Variable
Procedure.f DirTreeSize_f(id.l, Directory.s, *Num.GetNum) 
  Protected Name.s
  Protected Size.f, Entry.l
  If ExamineDirectory(id, Directory, "*.*") 
    While NextDirectoryEntry(id) 
      Entry = DirectoryEntryType(id)
      If Entry = #PB_DirectoryEntry_File 
        Size + DirectoryEntrySize(id)
        *Num\Files + 1
      ElseIf Entry = #PB_DirectoryEntry_Directory
        Name = DirectoryEntryName(id) ; Debug Name 
        If Name <> ".." And Name <> "." 
          Size + DirTreeSize_f(id + 1, Directory + Name + "\", *Num.GetNum) 
          *Num\Dirs + 1
        EndIf 
      EndIf 
    Wend
  EndIf 
  ProcedureReturn Size 
EndProcedure

;/ rekursive Ermittlung der Gesamtgröße der Dateien (in Bytes)
;/ in einem Verzeichnisbaum über eine Double-Variable
Procedure.d DirTreeSize_d(id.l, Directory.s, *Num.GetNum) 
  Protected Name.s
  Protected Size.d, Entry.l
  If ExamineDirectory(id, Directory, "*.*") 
    While NextDirectoryEntry(id) 
      Entry = DirectoryEntryType(id)
      If Entry = #PB_DirectoryEntry_File 
        Size + DirectoryEntrySize(id)
        *Num\Files + 1
      ElseIf Entry = #PB_DirectoryEntry_Directory
        Name = DirectoryEntryName(id) ; Debug Name 
        If Name <> ".." And Name <> "." 
          Size + DirTreeSize_d(id + 1, Directory + Name + "\", *Num.GetNum) 
          *Num\Dirs + 1
        EndIf 
      EndIf 
    Wend
  EndIf 
  ProcedureReturn Size 
EndProcedure

;Result.q = DirTreeSize_q(0, "C:\Programme\", @Total.GetNum)
Result.f = DirTreeSize_f(0, "C:\Programme\", @Total.GetNum)
;Result.d = DirTreeSize_d(0, "C:\Programme\", @Total.GetNum)
Debug Result
Debug Total\Files
Debug Total\Dirs

Verfasst: 15.08.2006 00:09
von Kaeru Gaman
> 8.172.071.838

passt noch nicht mal in eine Long, von daher auch nicht in eine Float, ohne ungenau zu werden.

natürlich hast du in sofern recht, dass der rückgabewert der funktion wie jede andere Variable auch sauber ge-cast-et werden müsste.
auch wenn es nicht sinnvoll sein dürfte, den wert mit einem Rundungsfehler zu bekommen.

Verfasst: 15.08.2006 09:13
von HeX0R
Kaeru Gaman hat geschrieben:> 8.172.071.838

passt noch nicht mal in eine Long, von daher auch nicht in eine Float, ohne ungenau zu werden.
*Autsch*
Also diese irrwitzige Aussage solltest du vielleicht doch lieber nochmal überdenken...

Verfasst: 15.08.2006 11:18
von jear
Das steckt noch ein mächtiger Bug in PB4 drin, auf den man Fred mal aufmerksam machen sollte.
Für den, den es interessiert, mein Problem habe ich nun so gelöst.

Code: Alles auswählen

Structure GetNum
  Files.l
  Dirs.l
EndStructure

Global NewList TreeMembers.s()

;/ rekursive Ermittlung aller Ordner unter der Root
;/ Ablage der Namen in der Liste TreeMember()
Procedure.l DirTreeMembers(id.l, Directory.s, *Num.GetNum)
  Protected Name.s, Entry.l
  If ExamineDirectory(id, Directory, "*.*") 
    While NextDirectoryEntry(id) 
      Entry = DirectoryEntryType(id)
      If Entry = #PB_DirectoryEntry_Directory
        Name = DirectoryEntryName(id) ; Debug Name 
        If Name <> ".." And Name <> "." 
          Name = Directory + Name + "\"
          AddElement(TreeMembers())
          TreeMembers() = Name
          DirTreeMembers(id+1, Name,*Num.GetNum)
          *Num\Dirs + 1
        EndIf 
      EndIf 
    Wend
  EndIf  
EndProcedure

;/ Ermittlung der Gesamtgröße der Dateien (in KBytes)
;/ in den Verzeichnissen die in der Liste TreeMembers() abgelegt sind
Procedure.l TreeSize(id.l, Directory.s, *Num.GetNum)  
  Protected Name.s
  Protected Size.q, Entry.l 
  DirTreeMembers(0, Directory, *Num.GetNum) 
  ForEach TreeMembers()
    If ExamineDirectory(1, TreeMembers(), "*.*") 
      While NextDirectoryEntry(1) 
        Entry = DirectoryEntryType(1)
        If Entry = #PB_DirectoryEntry_File 
          Size + DirectoryEntrySize(1) : *Num\Files + 1
        EndIf 
      Wend
    EndIf 
  Next
  ClearList(TreeMembers())
  ProcedureReturn Size/1024 
EndProcedure

Result.l = TreeSize(0, "C:\Programme\", @Total.GetNum)

Debug Result
Debug Total\Files
Debug Total\Dirs

Verfasst: 15.08.2006 11:31
von Kaeru Gaman
HeX0R hat geschrieben:*Autsch*
Also diese irrwitzige Aussage solltest du vielleicht doch lieber nochmal überdenken...
wieso? ist doch logisch.

erklär mir doch mal, wieso ich da falsch liegen soll?

Verfasst: 15.08.2006 12:00
von HeX0R
Weil Floats ihre 4 Bytes völlig anders benutzen.
Beispielsweise lässt sich eine Zahl:
1.099.511.627.776
kaum in ein Long stopfen, im Float dagegen lässt sie sich problemlos genau (also ohne Fehler) speichern.

Du kannst also bestimmt nicht behaupten keine Zahl, die zu gross für ein Long ist, lässt sich fehlerlos in einem Float speichern.

Verfasst: 15.08.2006 12:07
von Kaeru Gaman
HeX0R hat geschrieben:Weil Floats ihre 4 Bytes völlig anders benutzen.
Beispielsweise lässt sich eine Zahl:
1.099.511.627.776
kaum in ein Long stopfen, im Float dagegen lässt sie sich problemlos genau (also ohne Fehler) speichern.

Du kannst also bestimmt nicht behaupten keine Zahl, die zu gross für ein Long ist, lässt sich fehlerlos in einem Float speichern.
:lol:

nagut, für zweierpotenzen gilt da ne ausnahme...
aber du willst doch an der ausnahme keine aussage anpinnen?

in der regel lassen sich zahlen, die nicht in eine long passen, nicht fehlerfrei in einer float speichern.

was ja total logisch ist, weil die noch weniger bits für die mantisse hat, weil sie auch welche für den exponenten braucht.

und um als beispiel mal die zahl zu nehmen, die von jear genannt und von mir zitiert wurde:

Code: Alles auswählen

a.q = 8172071838
b.l = a
c.f = a
Debug a
Debug b
Debug c
sehen heißt glauben. ;)

----------------------------------------------------
PS:
statistik:
2^64 = 18446744073709551616 (window-calc, keine garantie)
2^23 = 00000000000008388608
die differenz liegt immer noch wesentlich über 18Trillionen.
von diesen sind nur (64-23)= 41 zahlen genau Zweierpotenzen,
lassen sich also fehlerfrei darstellen.
Das ist noch nicht mal ein gottverdammter Meßfehler!
und damit willst du meine Aussage in Zweifel ziehen?
GEH HEIM!