byterechner() - Bytes in größtmögliche Einheit umrechnen

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

byterechner() - Bytes in größtmögliche Einheit umrechnen

Beitrag von AND51 »

Wichtig!
Auf Seite 6 gibt es ein Update, welches etwas schneller ist, als der "Gewinner" (Gott, klingt das eingebildet) des deutschen Contests!
»»» Gehe zu Seite 6

Das Update benutzt auch keine 'booleschen Ausdrücke' mehr, diese werden offiziell nämlich nicht unterstützt!

———————————————————————————————————————

Hallo!

Edit: Hier habe ich den Code mal nach vorn geholt und gleichzeitig nocheinmal verbessert. (Update: 0 Byte wurden als 1- byte umgerechnet, Fehler behoben)

Code: Alles auswählen

Procedure.s byterechner(byte.q, NbDecimals.l=0)
	Protected unit.l
	If byte
		unit=Round(Log(byte)/Log(1024), 0)
	EndIf
	ProcedureReturn StrD(byte/Pow(1024, unit), NbDecimals*(unit And 1))+" "+StringField("Byte,KB,MB,GB,TB,PB,EB", unit+1, ",")
EndProcedure

Debug byterechner(-4096) ; ungültige Angabe wird zu "-1 Byte"
Debug byterechner(0) ; Eine Null-Byte große Datei bleibt auch 0 Byte groß :)
Debug byterechner(27101988) ; Bisherige Angaben bleiben ok
  • Funktionstüchtig mit PB 4.01+
    Beschreibung: Geht bis 8.999.999.999.999.999.999 Byte (7,8 EB)

Hier meine neue PB 4 Byterechner Prozedur.
rechnet beliebige Anzahl an Bytes mit Hilfe des neuen Types Quad in die größtmögliche Einheit um. Wer weiß schon, wie viel 4096096 Byte in KB sind?^^

Wer mag, kann ja die Prozedur erweitert hier posten, sodass ein oder zwei Stellen hinter dem Komma unrerstützt werden. Ich habe ein bisschen mit Modulo versucht, aber sofort die Krise gekriegt. Wäre an der extended Version interessiert :allright:
Meine Version rundet nämlich ab, weil es ja alles hinterm Komma weglässt.

Meine ältere Version des Byterechners arbeitete mit Floats, die Prozedur fliegt ie im Forum irgendwo noch rum. Diese unterstützte Kommazahlen, konnte dafür aber nicht so weit wie diese hier rechnen.

Code: Alles auswählen

Procedure.s byterechner(byte.q)
	Protected einheit.s
	
	If byte < 1024
		ProcedureReturn Str(byte)+" Byte"
	EndIf
	If byte >= 1024
		byte/1024
		einheit.s=" KB"
	EndIf
	If byte >= 1024
		byte/1024
		einheit.s=" MB"
	EndIf
	If byte >= 1024
		byte/1024
		einheit.s=" GB"
	EndIf
	If byte >= 1024
		byte/1024
		einheit.s=" TB"
	EndIf
	If byte >= 1024
		byte/1024
		einheit.s=" PB"
	EndIf
	If byte >= 1024
		byte/1024
		einheit.s=" EB"
	EndIf
	
	ProcedureReturn Str(byte)+einheit.s
EndProcedure

Debug byterechner(4096096) ; 3 MB
Debug byterechner(1024) ; 1 KB 
Debug byterechner($FFFFFF) ; 15 MB
Debug byterechner(21456985147) ; 19 GB
Zuletzt geändert von AND51 am 16.10.2007 20:30, insgesamt 6-mal geändert.
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
nco2k
Beiträge: 892
Registriert: 08.09.2004 23:13

Beitrag von nco2k »

Code: Alles auswählen

Procedure.s ByteCalc(Value.q, NbDecimals.b = 0)
  Result.s = ""
  Bytes.d = PeekQ(@Value)
  If Bytes => 0 And NbDecimals => 0
    Unit.b = 0
    While Unit < 6 And Bytes => 1024
      Bytes / 1024
      Unit + 1
    Wend
    Result = StrD(Bytes, NbDecimals)
    Select Unit
      Case 0
        Result = StrD(ValD(Result), 0)+" Byte"
      Case 1
        Result+" KB"
      Case 2
        Result+" MB"
      Case 3
        Result+" GB"
      Case 4
        Result+" TB"
      Case 5
        Result+" PB"
      Case 6
        Result+" EB"
    EndSelect
  EndIf
  ProcedureReturn Result
EndProcedure

Debug ByteCalc(21456985147)
Debug ByteCalc(21456985147, 1)
Debug ByteCalc(21456985147, 2)
Debug ByteCalc(21456985147, 4)
c ya,
nco2k
~|__/
..o.o.. <--- This is Einkaufswagen. Copy Einkaufswagen into your signature to help him on his way to world domination.
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Danke schon mal für deinen Post!

Allerdings arbeitest du mit Doubles, ist da nicht der Wertebereich etwas beschränkt? Trotzdem: So hatte ich es auch vorher.

Das hochzählen mit den Units finde ich übrigens richtig elegant <)
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
nco2k
Beiträge: 892
Registriert: 08.09.2004 23:13

Beitrag von nco2k »

@AND51
> Allerdings arbeitest du mit Doubles, ist da nicht der Wertebereich etwas beschränkt?
hm.. eigentlich nicht. ich verwende ja sowohl quads als auch doubles und ich wüsste jetzt nicht wirklich, wie ich auf eine ungerundete nachkommastelle kommen soll, ohne floats/doubles zu verwenden.

c ya,
nco2k
~|__/
..o.o.. <--- This is Einkaufswagen. Copy Einkaufswagen into your signature to help him on his way to world domination.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
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 »

Das mit dem Bytes = PeekQ(@Value) hat bei mir bei ProcedureReturn
irgendeinen Fehler verursacht. Außerdem waren die Variablen lokal nicht
geschützt. Zusätzlich hab ich das Gewirr hinter Case 0 abgeändert.

Hier also meine Version:

Code: Alles auswählen

Procedure.s ByteCalc(Value.q, NbDecimals.l = 0)
  Protected result.s = "", Unit.l = 0, Bytes.d = Value
  
  If Bytes => 0 And NbDecimals => 0
    While Unit < 6 And Bytes => 1024
      Bytes / 1024
      Unit + 1
    Wend
    result = StrD(Bytes, NbDecimals)
    Select Unit
      Case 0 : result = StrQ(Value) + " Byte"
      Case 1 : result + " KB"
      Case 2 : result + " MB"
      Case 3 : result + " GB"
      Case 4 : result + " TB"
      Case 5 : result + " PB"
      Case 6 : result + " EB"
    EndSelect
  EndIf
  
  ProcedureReturn result
EndProcedure

Debug ByteCalc(21456985147)
Debug ByteCalc(21456985147, 1)
Debug ByteCalc(21456985147, 2)
Debug ByteCalc(21456985147, 4)
Debug ByteCalc(1024 * 1024 - 500, 4)
Debug ByteCalc(512, 1)
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

OK, ich schau noch mal nach.

Habe zwischenzeitlich deine prozedur etwas zusammengestampft:

Code: Alles auswählen

Procedure.s byterechner(byte.q, NbDecimals.c=0)
	Protected res$, bytes.d=PeekQ(@byte), unit.c
		While unit < 6 And Bytes > 1023
			bytes/1024
			unit+1
		Wend
		If unit
			res$=StrD(bytes, NbDecimals)+" "+StringField("KB,MB,GB,TB,PB,EB,ZB,YB", unit, ",")
		Else
			res$=StrD(bytes, 0)+" Byte"
		EndIf
	ProcedureReturn res$
EndProcedure
Ist das so nicht übersichtlicher?

Gleichzeitig sind die Variablen noch protected und es sind statt 127 nun 255 Nachkommastellen möglich falls irgend ein :freak: auf die Idee kommt :)


Edit: Oh, noch ein Konkrrent und Gleichgesinnter <)
Aber wozu brauche ich
  • Protected result.s = ""
? Der String ist anfangs doch eh null-initalisiert :wink:


btw. Bei mir verursacht das PeekQ() keinen Fehler.
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

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

@AND51:
Dieses blöde Ding gibt bei mir einen "Invalid Memory Access" in Zeile 8: Bytes.d=PeekQ(@Byte)

Wieso nicht so: Bytes.d = Byte ???

///Edit zum Edit von AND51:
Ohne PeekQ() geht es einwandfrei, also warum so umständlich?

Klar, das result.s = "" kann man weglassen, ein result.s reicht vollkommen.
Ich hab das so geschrieben, weil es vorher auch schon so da gestanden hat.
Zuletzt geändert von NicTheQuick am 11.10.2006 14:24, insgesamt 1-mal geändert.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

NicTheQuick hat geschrieben:Das mit dem Bytes = PeekQ(@Value) hat bei mir bei ProcedureReturn
irgendeinen Fehler verursacht.
Den Fehler hab ich bei Deiner Version :freak:
nco2 seine Version geht einwandfrei.
Haste vielleicht eine alte Lib oder sowas?
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
nco2k
Beiträge: 892
Registriert: 08.09.2004 23:13

Beitrag von nco2k »

@NicTheQuick
> PeekQ
ich hab PeekQ geschrieben weil irgendwo ein quad bug in pb shlummert der einen ima verursacht wenn ich Bytes.d = Value schreibe. komisch dass es bei dir andersrum ist.

> Protected
ich verwende nie protected da ich jeden code in prozeduren verpacke und ausserhalb von prozeduren keine variablen etc. rumliegen.

im endeffekt hast du den code nur deinem style angepasst, was absolut geschmackssache ist. ich persönlich hasse es Case 0 : ... zu schreiben.

@AND51
hab noch nie StringField() verwendet, nette idee.

c ya,
nco2k
~|__/
..o.o.. <--- This is Einkaufswagen. Copy Einkaufswagen into your signature to help him on his way to world domination.
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Jetzt bin ich auf jeden Fall Spitzenreiter mit nur 8 Zeilen: :D
Arbeite auch ganz ohne Strings und spart in der While-Zeile auch noch 1 Byte, indem ich >= 1024 durch > 1023 ersetze. Rein theorethisch müsste diese Ersetzung sogar einen -wenn auch minimalen- Performanceschub bringen, oder?

Code: Alles auswählen


; LEICHT FEHLERBEHAFTET - Siehe nächsten Post für korrigierte Version

Procedure.s byterechner(byte.q, NbDecimals.c=0)
	Protected bytes.d=PeekQ(@byte), unit.c=1
		While unit < 6 And bytes > 1023
			bytes/1024
			unit+1
		Wend
		ProcedureReturn StrD(bytes, NbDecimals*(Not (NbDecimals And bytes < 1024)))+" "+StringField("Byte,KB,MB,GB,TB,PB,EB", unit, ",")
EndProcedure
Ich habe mich auch gefragt: Warum PeekQ(). OK, wer's braucht, lässt's, wer's nicht braucht, streicht es und spart 5 Byte :wink:

@ nco2k: Danke! Ich könnte mir ein Leben ohne Stringfield() allerdings nicht mehr vorstellen... :lol:
Zuletzt geändert von AND51 am 11.10.2006 14:46, insgesamt 1-mal geändert.
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Antworten