AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Power funktioniert nicht wie gedacht

Ein Thema von DieDolly · begonnen am 24. Jul 2018 · letzter Beitrag vom 25. Jul 2018
Antwort Antwort
THY4243

Registriert seit: 15. Dez 2012
Ort: München - Untermenzing
46 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: Power funktioniert nicht wie gedacht

  Alt 24. Jul 2018, 22:22
Vielleicht helfe ich euch und auch mir, wenn ich mein Problem erkläre.
Ich habe ein TEdit sowie eine TComboBox. Im Edit kann ich eine Zahl eingeben und in der ComboBox kann ich von Byte bis Gigabyte alles auswählen.
Die eingegebene Zahl soll später in das umgerechnet werden, was ich in der ComboBox ausgewählt habe. Das schaffe ich. Aber wie außer mit try except fange ich Fehleingaben ab, sodass die Zahl niemals größer wird als 1099511627775 Bytes (1TB-1Byte)
Deine Erklärung geht in eine zweite Richtung (neben dem mathemat. Thema)? Wenn es um das "Abfangen" geht, müsstest Du nach jedem Tastendruck das TEdit-Feld auswerten und auf Gültigkeit in Deinem Sinn berechnen. Das würde mittels der Ereignisse des TEdit gehen.
Da ja auch Buchstaben in TEdit möglich sind ... : https://www.delphipraxis.net/19039-e...rlauben-2.html
  Mit Zitat antworten Zitat
DieDolly

Registriert seit: 22. Jun 2018
2.175 Beiträge
 
#2

AW: Power funktioniert nicht wie gedacht

  Alt 24. Jul 2018, 22:27
Ich habe meine Funktion jetzt angepasst. Maximaledateigröße 16 EiB minus 1 KiB. Laut Wikipedia die größte zulässige Dateigröße unter NTFS.
Die Funktion funktioniert soweit ganz gut und macht genau was ich brauche.

Delphi-Quellcode:
function CalculateSize(Bytes, Multiplier: UInt64): UInt64;
const
 MaxSize: UInt64 = 18446744073709551615 - 1024; // 16 EiB - 1 KiB
var
 dTmp: Double;
begin
 if Multiplier > 0 then
  dTmp := System.Math.Power(1024, Multiplier)
 else
  dTmp := 1;

 dTmp := Bytes * dTmp;

 if dTmp > MaxSize then
  dTmp := MaxSize;

 Result := Trunc(dTmp);
end;
Einen Integer-Overflow sollte es eigentlich wegen if dTmp > MaxSize then dTmp := MaxSize; nicht geben.
Statt Round, was Int64 erwartet, nehme ich jetzt Trunc. Damit sollte alles normalisiert werden.

Ok einen Overflow bekomme ich mit Round und Trunc trotzdem noch wenn dTmp = Maxsize ist.

Wenn ich MaxSize auf 1152921504606847000 (1 EiB) verkleinere, ist das Problem erledigt.
So lasse ich das jetzt auch. Denn ich denke niemand wird jemals eine Datei >1 EiB erzeugen. Und wenn, dann sind es Aliens.

Geändert von DieDolly (24. Jul 2018 um 22:57 Uhr)
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
778 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Power funktioniert nicht wie gedacht

  Alt 25. Jul 2018, 00:53
Nicht gut: Durch Umwandlung von uint64 zu double und zurück zu uint64 verlierst du bei grossen Zahlen an Präzision.

Grund: double ist nur auf ca. 15 Stellen (dezimal) präzis während uint64 Werte 19 stellig sein können.

http://docwiki.embarcadero.com/RADStudio/Tokyo/de/Interne_Datenformate_(Delphi)


Beispiele:
9000000000000000512 wird durch Umwandlung in double und zurück zu uint64 zu
9000000000000000000

9000000000000000513 wird zu 9000000000000001024


Wenn du mit uint64 Genauigkeit rechnen willst, dann verzichte auf double.

Deine uint64 Power Funktion könnte so aussehen:

Delphi-Quellcode:
function Power( exp : integer ) : uint64;
begin
  Result := uint64(1) shl (exp*10); // exp in [0..6] check einbauen
end;
Michael Gasser
  Mit Zitat antworten Zitat
DieDolly

Registriert seit: 22. Jun 2018
2.175 Beiträge
 
#4

AW: Power funktioniert nicht wie gedacht

  Alt 25. Jul 2018, 01:09
Das funktioniert perfekt!

Delphi-Quellcode:
function ConvertBytes(Bytes: UInt64; Multiplier: Integer): UInt64;
const
 // When the calculated filesize is bigger than MaxSize, than normalise it to MaxSize.
 // I think nobody (not a "normal" person) would ever create a file bigger than 1 EiB
 MaxSize: UInt64 = 1152921504606847000; // 1 EiB
begin
 if Multiplier> 0 then
  Result := UInt64(1) shl (Multiplier* 10)
 else
  Multiplier:= 1;

 Result := Bytes * Result;

 if Result > MaxSize then
  Result := MaxSize;
end;

Geändert von DieDolly (25. Jul 2018 um 01:13 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von TigerLilly
TigerLilly

Registriert seit: 24. Mai 2017
Ort: Wien, Österreich
1.251 Beiträge
 
Delphi 12 Athens
 
#5

AW: Power funktioniert nicht wie gedacht

  Alt 25. Jul 2018, 06:12
Der Thread ist ein gutes Beispiel für "Wie löse ich anstelle meines Problems eines, das es gar nicht gibt, und zwar so, dass es keiner versteht?".

Das zu lösende Problem ist doch, dass es "rundherum" Beschränkungen in den erwarteten Typen gibt. Das sollte gelöst werden.
Wenn das - warum auch immer - nicht geht, dann ist die Aufgabenstellung sinnvoll zu lösen und das Ergebnis auf die Typen brauchbar abzubilden.

Jetzt gibt es eine Lösung, die MaxSize zurückliefert, auch wenn der richtige Wert > MaxSize wäre. Gar nicht gut.

if Multiplier> 0 then
Result := UInt64(1) shl (Multiplier* 10) // Das versteht keiner auf den ersten Blick.
else
Multiplier:= 1; // Das ist Irreführung - wird ja gar nicht mehr verwendet.

Result := Bytes * Result; // Welchen Wert hat Result, wenn Multiplyer 0 ist?

if Result > MaxSize then
Result := MaxSize; // das tut in der Seele weh
  Mit Zitat antworten Zitat
madas

Registriert seit: 9. Aug 2007
207 Beiträge
 
#6

AW: Power funktioniert nicht wie gedacht

  Alt 25. Jul 2018, 06:19
Der Thread ist ein gutes Beispiel für "Wie löse ich anstelle meines Problems eines, das es gar nicht gibt, und zwar so, dass es keiner versteht?".

Das zu lösende Problem ist doch, dass es "rundherum" Beschränkungen in den erwarteten Typen gibt. Das sollte gelöst werden.
Wenn das - warum auch immer - nicht geht, dann ist die Aufgabenstellung sinnvoll zu lösen und das Ergebnis auf die Typen brauchbar abzubilden.

Jetzt gibt es eine Lösung, die MaxSize zurückliefert, auch wenn der richtige Wert > MaxSize wäre. Gar nicht gut.

if Multiplier> 0 then
Result := UInt64(1) shl (Multiplier* 10) // Das versteht keiner auf den ersten Blick.
else
Multiplier:= 1; // Das ist Irreführung - wird ja gar nicht mehr verwendet.

Result := Bytes * Result; // Welchen Wert hat Result, wenn Multiplyer 0 ist?

if Result > MaxSize then
Result := MaxSize; // das tut in der Seele weh
Wenn der Thread Ersteller schreibt er möchte Byte in MB oder GB umrechnen, verstehe ich nicht warum die Ergebnisse dann größer werden sollen.
  Mit Zitat antworten Zitat
DieDolly

Registriert seit: 22. Jun 2018
2.175 Beiträge
 
#7

AW: Power funktioniert nicht wie gedacht

  Alt 25. Jul 2018, 07:54
Vielleicht ist es so klarer.

Ich habe einen numerischen Wert und die Zusatzinformation, ob das B, KiB, MiB, GiB oder TiB sein sollen.

Rufe ich meine (umbenannte) Funktion nun so auf, erhalte ich 46080 Bytes.
Delphi-Quellcode:
type
  TFileSizes = (_B, _KiB, _MiB, _GiB, _TiB, _PiB);

Ausgabe := ConvertToBytes(45, _KiB);
Ich speichere also irgendwo auf der Festplatte 45 sowie die Zusatzinfo (Speichergröße) ab statt große Zahlen.

Zitat:
// Welchen Wert hat Result, wenn Multiplyer 0 ist?
Im Beispiel oben wären das 45 (Bytes).

Zitat:
if Result > MaxSize then
Result := MaxSize; // das tut in der Seele weh
Warum sollte man jemals höher als 1 EiB gehen? So große Datenmengen gibt es sicherlich insgesamt. Aber ich habe im privatanwenderbereich noch niemanden gesehen, der eine einzelne Datei hat die so groß ist. Angenommen durch falsche Eingaben hat Result schließlich einen Wert von 1 YiB, dann führt das zu einem Fehler.
Da im im weiteren Verlauf aber zwingend Int64 brauche, kann ich hier keine Fließkommazahlen nutzen.

Zitat:
Result := UInt64(1) shl (Multiplier* 10) // Das versteht keiner auf den ersten Blick.
Das ist dasselbe wie Power(1024, 2).

Zitat:
// das tut in der Seele weh
Hilfe nehme ich sehr gerne an! Ich meine jetzt keine Seelenhilfe oder so sondern programmiertechnisch.

Geändert von DieDolly (25. Jul 2018 um 08:07 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.557 Beiträge
 
Delphi 12 Athens
 
#8

AW: Power funktioniert nicht wie gedacht

  Alt 25. Jul 2018, 11:07
Das versteht keiner auf den ersten Blick.
Wobei es genau das aussagt, was da ursprünglich auch gemacht wurde, bzw. weswegen es nunmal 1024 sind und nicht 1000.
Delphi-Quellcode:
// 0=Byte 1=KB 2=MB 3=GB

Multiplikator := 1024 shl (10 * Exponent);
// oder
Anzeigewert := Wert shr (10 * Exponent);
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:01 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz