ENGLISH VERSION |
|
Links | | | Forum | | | Kommentare | | | News melden |
Chat | | | Umfragen | | | Newsticker | | | Archiv |
amiga-news.de Forum > Programmierung > Partionsgröße in 64 Bit | [ - Suche - Neue Beiträge - Registrieren - Login - ] |
-1- | [ - Beitrag schreiben - ] |
14.08.2007, 22:57 Uhr MaikG Posts: 5172 Nutzer |
Ich hab einen C-Code, der macht für kleine Partitionen korrekte Werte, für große nicht. Da war was mit NSD und TD64. Also müsste man jetzt alles ändern oder geht das irgendwie indem man eine 64 Bit Variable verwendet? Im letzteren falle wie? Der Compiler wird sowas vermutlich nicht direkt unterstützten weil der alt ist. code:if (lock=Lock(file,SHARED_LOCK)) { if (Info(lock,idata)) { usedbytes=idata->id_NumBlocksUsed*idata->id_BytesPerBlock; totalbytes=idata->id_NumBlocks*idata->id_BytesPerBlock; apu1=totalbytes>>10; if(apu1) percent=(usedbytes>>10)*100/apu1; ret=1; } UnLock(lock); } Also in Kilobytes oder Megabytes würde mir das reichen. Da müsste man doch irgendwie die Multiplikation mit einer division um 1024 ergänzen können und damit den ULONG bereich nicht überschreiten. Aber ich brauch auch prozent, das mit dem Shiften verstehe ich da nicht. [ Dieser Beitrag wurde von MaikG am 14.08.2007 um 23:52 Uhr geändert. ] [ - Antworten - Zitieren - Direktlink - ] |
15.08.2007, 08:52 Uhr thomas Posts: 7717 Nutzer |
Die MB kannst du so herausfinden: blocks_per_mb = 1024*1024 / BytesPerBlock; disk_size = NumBlocks / blocks_per_mb; used_mb = NumBlocksUsed / blocks_per_mb; free_mb = disk_size - used_mb; Das setzt voraus, daß die Disk größer ist als ein MB und eine Blockgröße hat, die ein MB ganzzahlig teilt. Das kannst du natürlich auch mit KB machen, aber Blöcke größer als ein KB sind durchaus nicht selten und damit funktioniert das nicht (die erste Division ergibt dann 0). Zitat: Klar. Wenn dein Compiler 64bit-Variablen unterstützt (das kann meines Wissens nur der GCC), dann kannst du deine Variablen einfach als long long oder unsigned long long deklarieren und hast keine Probleme mehr. Zitat: Der rechnet halt mit KB. Ersetze >> 10 einfach durch / 1024. Die 1024 kannst du dann rauskürzen. Gruß Thomas -- Email: thomas-rapp@web.de Home: thomasrapp.homepage.t-online.de/ [ Dieser Beitrag wurde von thomas am 15.08.2007 um 08:56 Uhr geändert. ] [ - Antworten - Zitieren - Direktlink - ] |
15.08.2007, 09:49 Uhr MaikG Posts: 5172 Nutzer |
>Das setzt voraus, daß die Disk größer ist als ein MB und eine >Blockgröße hat, die ein MB ganzzahlig teilt. Das ist schlecht. Einmal kann es sich auch um z.B. 880kB handeln und das mit dem Teilen ergibt das nur einen ungenauen oder falschen wert? >Das kannst du natürlich auch mit KB machen, aber Blöcke größer als >ein KB sind durchaus nicht selten und damit funktioniert das nicht >(die erste Division ergibt dann 0). Es kann im gesamten Amiga-gültigen bereich liegen. >Klar. Wenn dein Compiler 64bit-Variablen unterstützt (das kann >meines Wissens nur der GCC), dann kannst du deine Variablen >einfach als long long oder unsigned long long deklarieren und hast >keine Probleme mehr. SASC ist älter als GCC und vbcc und fällt damit wohl aus. >Der rechnet halt mit KB. Ersetze >> 10 einfach durch / 1024. Die 1024 kannst du dann rauskürzen. Eigentlich müssten das Bytes gewesen sein, weil später kommt noch eine fallunterscheidung wo dann Bytes>Kbytes werden wenn >1024 und das selbe dann noch in MB. Ja nun müsste ich praktisch auch sowas ähnliches machen, aber woher weiss ich vorher ohne den ULONG bereich zu überschreiten ob die Disk als Bytes, Kbytes oder Mbytes anzugeben ist? [ - Antworten - Zitieren - Direktlink - ] |
15.08.2007, 10:59 Uhr Holger Posts: 8116 Nutzer |
Zitat:Dann lass es weg. Wie berechnet man Prozentwerte? Aktueller Werte geteilt durch Grundwert mal hundert. Also: C code:Die Blöckgröße spielt für die prozentuale Auslastung überhaupt keine Rolle. Sie steht ja auch in Deiner Fassung auf beiden Seiten des Bruchstrichs.if (lock=Lock(file,SHARED_LOCK)) { if (Info(lock,idata)) { percent=idata->id_NumBlocksUsed*100/idata->id_NumBlocks; ret=1; } UnLock(lock); } Jetzt hast Du nur noch das Problem, dass die Anzahl der Blöcke sehr groß sein und idata->id_NumBlocksUsed*100 einen Überlauf erzeugen könnte. Da C so eine grottige Sprache ist, die Dir das nicht mitteilt (obwohl die CPU das jedesmal überprüft und im Flag-Register anzeigt), musst Du vorher eine Fallunterscheidung machen. C code:Die Berechnungvariante für große Zahlen verursacht keinen Überlauf, würde aber bei kleinen Zahlen zu Rundungsfehlern führen. Deshalb die Fallunterscheidung.if (lock=Lock(file,SHARED_LOCK)) { if (Info(lock,idata)) { unsigned int used=idata->id_NumBlocksUsed, max=idata->id_NumBlocks, largest=~0; if(largest/100 < used) // potential overflow percent=used/(max/100); else percent=used*100/max; ret=1; } UnLock(lock); } mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
15.08.2007, 11:15 Uhr Holger Posts: 8116 Nutzer |
Zitat:Ok. Problem Nr. 2. Das ist eigentlich dem Prozentproblem ähnlich. Du vermeidest Überlaufe am leichtesten, in dem Du die zugehörigen Berechnungen vermeidest. Wenn Du die Größe in kB oder MB angeben möchtest, dann rechne die Größe in bytes, die einen Überlauf verursachen könnte, gar nicht erst aus. Die kleinste zulässige (und am häufigsten benutzte) blockgröße ist 512 bytes, also ein halbes kB. In diesem Fall musst Du die Anzahl Blöcke nur durch zwei teilen und Du hast die Angabe in kB. Ansonsten ermittle den Faktor, der durch die Blockgröße bestimmt wird, und benutze ihn. Allerdings kann bei großen Blöcken auch ein Überlauf stattfinden, dann kommst Du um 64 Bit Arithmetik nicht herum. Hier erst mal die einfache Variante: C code:if(lock=Lock(file,SHARED_LOCK)) { if(Info(lock,idata)) { switch(idata->id_BytesPerBlock) { unsigned int blockFactor; // half kB case 512: // mostly used usedkB=idata->id_NumBlocksUsed>>1; // num/2 totalkB=idata->id_NumBlocks>>1; case 1024: // not so common, but easy to optimize usedkB=idata->id_NumBlocksUsed; totalkB=idata->id_NumBlocks; default: blockFactor=idata->id_BytesPerBlock/512; usedkB=(idata->id_NumBlocksUsed*blockFactor)>>1; totalkB=(idata->id_NumBlocks*blockFactor)>>1; } ret=1; } UnLock(lock); } Das kommt ohne 64 Bit Arithmetik aus, hat allerdings einen Überlauf bei Größen ab 2147483647,5 kB also 2048 GB großen Partitionen. Wenn ich mich jetzt nicht verrechnet habe. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
15.08.2007, 11:23 Uhr MaikG Posts: 5172 Nutzer |
Das mit Prozent klingt schon ganz gut, aber muss das nicht ULONG heissen? Okay, ich hab jetzt mal folgendes gemacht, das Ergebniss von (totalbytes/1024)*BlocksperTrack in einer Double - die kann ja 8 Byte erfassen. Dann eine fallunterscheidung, je nachdem ob es einen Overflow gibt oder nicht die Normale Routine oder ebend gleich durch 1024 rechnen. Problem ist der Compiler sagt ich muss einen Math Library linken, ich weiss aber nicht mehr wie das geht. Hab bei include schon math.h 68881.h usw. abgegeben. [ - Antworten - Zitieren - Direktlink - ] |
15.08.2007, 11:46 Uhr akl Posts: 265 Nutzer |
@MaikG: Du kannst die Funktion UMult64() aus der utility.library verwenden, müsstest Dir dann aber unter SAS/C per getreg() die oberen 32 Bit holen, also sowas in der Art: ULONG result[2]; result[1] = UMult64(numblocks, blocksize); result[0] = getreg(1); In result[0] kannst Du die GBs oberhalb 4 GB ablesen und aus result[1] die restlichen MB/KB berechnen. [ - Antworten - Zitieren - Direktlink - ] |
15.08.2007, 11:51 Uhr MaikG Posts: 5172 Nutzer |
>Das kommt ohne 64 Bit Arithmetik aus, hat allerdings einen Überlauf bei Größen ab 2147483647,5 kB also 2048 GB großen Partitionen. Cool, das geht bis 2048 GB ist okay. Prozent hat sich damit schon automatisch gefixt... Danke! >Du kannst die Funktion UMult64() aus der utility.library verwenden, müsstest Dir dann aber unter SAS/C per getreg() die oberen 32 Bit holen, also sowas in der Art: klingt auch nicht schlecht muss ich mir mal merken. [ - Antworten - Zitieren - Direktlink - ] |
15.08.2007, 11:52 Uhr Holger Posts: 8116 Nutzer |
Zitat:Wie Du willst. Sollte das gleiche ergeben... Zitat:Das ist aber totaler Quatsch. Bei double gibt's keinen Overflow, sondern allenfalls Rundungsfehler. Und wie gesagt, rechne keine übergroßen Produkte aus, die Du danach wieder durch die gleichen Beträge dividieren musst. Dann kannst Du Dir das alles sparen. Übrigens wüsste ich jetzt nicht, was bei (totalbytes/1024)*BlocksperTrack sinnvolles herauskommen soll. Zitat:-lm (in der Kommandozeile) Aber lass einfach den Quatsch mit der double-Zahl weg, und spar Dir das. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
15.08.2007, 11:57 Uhr thomas Posts: 7717 Nutzer |
@MaikG: Mach's doch nicht so kompliziert. code:blocks_per_mb = 1024*1024 / BytesPerBlock; disk_size = NumBlocks / blocks_per_mb; /* size in mb */ if (disk_size < 1024) /* disk is smaller than 1GB */ { disk_size = NumBlocks * BytesPerBlock / 1024; /* size in kb */ used_kb = NumBlocksUsed * BytesPerBlock / 1024; free_kb = disk_size - used_kb; used_percent = used_kb * 100 / disk_size; free_percent = free_kb * 100 / disk_size; } else { disk_size *= 1024; /* mb -> kb */ used_kb = NumBlocksUsed / blocks_per_mb * 1024; free_kb = disk_size - used_kb; used_percent = used_kb / (disk_size / 100); free_percent = free_kb / (disk_size / 100); } Gruß Thomas -- Email: thomas-rapp@web.de Home: thomasrapp.homepage.t-online.de/ [ - Antworten - Zitieren - Direktlink - ] |
15.08.2007, 12:11 Uhr Holger Posts: 8116 Nutzer |
Zitat:Wer sagt, dass die Partition voll sein muss? Da lässt Du aber ganz schöne Rundungsfehler zu. Wenn die Präzision man gerade für MB reicht, sollte man auch keine Zahlen in kB ausspucken. Zitat:Wo wir schon bei "nicht so kompliziert" sind:code:used_percent = used_kb / (disk_size / 100); free_percent = free_kb / (disk_size / 100); code:used_percent = used_kb / (disk_size / 100); free_percent = 100-used_percent; macht die Sache einfacher und vermeidet durch Rundung verursachte offensichtliche Falschanzeigen, deren Screenshots sich manche User so gerne ins Netz stellen, um sich darüber zu amüsieren. mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
15.08.2007, 12:27 Uhr Holger Posts: 8116 Nutzer |
C code:ULONG valueIsMB=0, used, max; if (lock=Lock(file,SHARED_LOCK)) { if (Info(lock,idata)) { ULONG largest=~0; used=idata->id_NumBlocksUsed, max=idata->id_NumBlocks; percent=(largest/100 < used)? // potential overflow used/(max/100): used*100/max; switch(idata->id_BytesPerBlock) { ULONG blockFactor; // half kB case 512: // mostly used used>>=1; // num/2 max>>=1; break; case 1024: break;// not so common, but easy to optimize default: blockFactor=idata->id_BytesPerBlock>>9; if(largest/blockfactor < used) { used=(used*blockFactor)>>1; max=(max*blockFactor)>>1; } else { ULONG blockPerMB=(1<<20)/idata->id_BytesPerBlock; valueIsMB=1; used/=blocksPerMB; max/=blocksPerMB; } } ret=1; } UnLock(lock); if(valueIsMB) printf("used %d MB, total %d MB, %d %%n", used, max, percent); else printf("used %d kB, total %d kB, %d %%n", used, max, percent); } Da müsste jetzt alles drin sein... mfg -- Good coders do not comment. What was hard to write should be hard to read too. [ - Antworten - Zitieren - Direktlink - ] |
15.08.2007, 15:03 Uhr Der_Wanderer Posts: 1229 Nutzer |
Wobfür wurden denn Floats erfunden ? Rechne doch alles in Float oder Double aus. Am Ende kannst du es auf MB scalieren. -- Thilo Köhler, Author von: HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, TK AB3 Includes und viele mehr... Homepage: http://www.hd-rec.de [ - Antworten - Zitieren - Direktlink - ] |
15.08.2007, 15:13 Uhr Der_Wanderer Posts: 1229 Nutzer |
Hier ein Beispiel (Amiblitz3/dos.include):code:--;/////////////////////////////////////////////////////////////////////////////// ;/ / ;/ Syntax: result.w = dos_CheckDiskSpace {disk.s,bytes.f} / ;/ / ;/ Description: / ;/ Check if there is bytes.f amount of memory on the given disk path availab:: / ;/ le. / ;/ Note: "bytes.f" is a float value, and is allowed to be greater than 2GB. / ;/ / ;/ Inputs: / ;/ - disk.s : name of a disk or directory, e.g. "Sys:" or "Sys:T" / ;/ - bytes.f : number of bytes / ;/ / ;/ Result: / ;/ - result.w : -1 if the memory is available, 0 if not / ;/ / ;/////////////////////////////////////////////////////////////////////////////// Function.w dos_CheckDiskSpace {disk.s,bytes.f} succ.w = False lock.l=Lock_(&disk.s,#ACCESS_READ) If lock DEFTYPE .InfoData idat If Info_(lock, idat) If idatid_DiskState = #ID_VALIDATED nbu.f = idatid_NumBlocksUsed nb.f = idatid_NumBlocks bpb.f = idatid_BytesPerBlock bytes_total.f = nb * bpb bytes_used.f = nbu * bpb bytes_free.f = bytes_total - bytes_used If bytes_free>bytes Then succ = True End If End If UnLock_ lock EndIf Function Return succ End Function Thilo Köhler, Author von: HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, TK AB3 Includes und viele mehr... Homepage: http://www.hd-rec.de [ - Antworten - Zitieren - Direktlink - ] |
15.08.2007, 18:29 Uhr MaikG Posts: 5172 Nutzer |
Funktioniert doch schon, musste nur bei prozent für disketten nochmal eine fallunterscheidung machen... [ - Antworten - Zitieren - Direktlink - ] |
-1- | [ - Beitrag schreiben - ] |
amiga-news.de Forum > Programmierung > Partionsgröße in 64 Bit | [ - Suche - Neue Beiträge - Registrieren - Login - ] |
Impressum |
Datenschutzerklärung |
Netiquette |
Werbung |
Kontakt
Copyright © 1998-2024 by amiga-news.de - alle Rechte vorbehalten. |