Seite 1 von 1

byteformat - Was ist schöner

Verfasst: Dienstag 17. Juli 2007, 09:35
von veers
Ihr kennt bestimmt alle das Problem 100000000 Bytes ist nicht aussagekräftig, wie wäre es mit 95.37 Megabytes ;)

Gut, das Problem ist einfach zu Lösen. Ich habe jedoch zwei Lösungen und kann mich nicht wirklich für eine entscheiden. Deshalb und vor allem aus Neugierde möchte ich von euch wissen welches ist der schönste weg ;)

Meine zwei Versionen:

o(n) - ~ 4.5 usec/durchlauf

Code: Alles auswählen

def byteformat(n, units=('', 'kilo', 'mega', 'giga', 'terra')):
    i = 0    
    while n >= 1024.0 and i < len(units):
        n /= 1024.0
        i += 1
    return "%.2f %sbytes" % (n, units[i])
O(1) - ~7 usec/durchlauf

Code: Alles auswählen

def byteformatlog(n, units=('', 'kilo', 'mega', 'giga', 'terra')):
    i = int(math.log(n, 1024))
    if i >= len(units): i = len(units) - 1
    n /= 1024.0**i 
    return "%.2f %sbytes" % (n, units[i])
Die Benötigte Zeit wurde mit timeit und 102'400'000 als Argument gemessen.

Was meint ihr dazu? Hat jemand eine hübschere Lösung?

Verfasst: Dienstag 17. Juli 2007, 09:57
von BlackJack
Bei der ersten Lösung sind `i` und die "komplizierte" Abbruchbedingung der ``while``-Schleife, Dinge die ich beseitigen würde (ungetestet):

Code: Alles auswählen

from __future__ import division

def byteformat(n, units=('', 'kilo', 'mega', 'giga', 'terra')):
    for unit in units:
        if n < 1024:
            break
        n /= 1024
    return '%.2f %sbytes' % (n, unit)

Verfasst: Dienstag 17. Juli 2007, 10:27
von veers
Nett :)
Hab die anderen beiden auch noch so umgeschrieben dass sie "from __future__ import division" verwenden.

Zeiten:
byteformat: 4.5 -> gleich
byteformaglog: 6.6 -> schneller!
byteformatfor (blackjack): 3.5 -> am schnellsten (:

Verfasst: Dienstag 17. Juli 2007, 13:16
von birkenfeld
Übrigens stimmen die Präfixe nicht. Wenn du 1024 als Basis verwendest, musst du "kibi", "mibi" etc. voranstellen.

</nitpick>

Verfasst: Dienstag 17. Juli 2007, 13:33
von veers
birkenfeld hat geschrieben:Übrigens stimmen die Präfixe nicht. Wenn du 1024 als Basis verwendest, musst du "kibi", "mibi" etc. voranstellen.

</nitpick>
Kibibyte tönt einfach nicht gut. Ich könnts natürlich noch kilo binary bytes, kib oder einfach KB nennen... :roll: Aber du hast schon recht, das sollte ich noch überdenken :)

Verfasst: Dienstag 17. Juli 2007, 14:04
von lunar
Wie wäre es mit dieser Lösung? Die ist aus einer Python-Implementierung von "du", die ich mal irgendwo im Netz gefunden habe, und auf meiner Platte abgelegt habe (also nicht von mir selbst geschrieben, wenn jemand die Quelle weiß, bitte sagen).

Verfasst: Dienstag 17. Juli 2007, 14:56
von veers
lunar hat geschrieben:Wie wäre es mit dieser Lösung? Die ist aus einer Python-Implementierung von "du", die ich mal irgendwo im Netz gefunden habe, und auf meiner Platte abgelegt habe (also nicht von mir selbst geschrieben, wenn jemand die Quelle weiß, bitte sagen).
Hm ich weis ja nicht... Da gefällt mir die Lösung von Blackjack oder meine mit log besser. :)

http://code.djangoproject.com/browser/d ... rs.py#L503
Hier sieht man noch wies in Django gelöst ist. Finde ich aber auch nicht schön. Dafür vermutlich schnell.

Verfasst: Dienstag 17. Juli 2007, 15:56
von Y0Gi
Kann man da nicht was mit Bitshifting machen?

Was diese Kibi-/Mibi-/Kiwi-/Hiwi-Benennungssache angeht, die kommt in meinen Augen reichlich spät und hört sich echt doof an ;)

Verfasst: Dienstag 17. Juli 2007, 16:42
von veers
Y0Gi hat geschrieben:Kann man da nicht was mit Bitshifting machen?

Was diese Kibi-/Mibi-/Kiwi-/Hiwi-Benennungssache angeht, die kommt in meinen Augen reichlich spät und hört sich echt doof an ;)
floats shiften kommt nicht gut (:

Verfasst: Mittwoch 18. Juli 2007, 08:05
von veers
BlackJack hat geschrieben:

Code: Alles auswählen

from __future__ import division

def byteformat(n, units=('', 'kilo', 'mega', 'giga', 'terra')):
    for unit in units:
        if n < 1024:
            break
        n /= 1024
    return '%.2f %sbytes' % (n, unit)
Die Lösung hat ein Problem:

Code: Alles auswählen

In [2]: lib.byteformat(1024**4)
Out[2]: '1.00 TiB'

In [3]: lib.byteformat(1024**5)
Out[3]: '1.00 TiB'

In [4]: lib.byteformat(1024**6)
Out[4]: '1024.00 TiB'
Es wird auch durch 1024 Dividiert wenn keine nächste Einheit vorhanden ist. :?

Das Problem würde sich zwar für die nächsten 100 Jahre verbergen lassen in dem units bis yota erweitert wird. Aber hübsch ist es dennoch nicht.

Verfasst: Mittwoch 18. Juli 2007, 09:53
von BlackJack
Okay, dann spendieren wir für die ganz grossen Platten/Dateien noch eine Multiplikation:

Code: Alles auswählen

def byteformat(n, units=('', 'kilo', 'mega', 'giga', 'terra')):
    for unit in units:
        if n < 1024:
            break
        n /= 1024
    else:
        n *= 1024
    return '%.2f %sbytes' % (n, unit)

Verfasst: Donnerstag 19. Juli 2007, 08:49
von Leonidas
Die Einheit ist aber dennoch eher noch Terabyte und nicht Terrabyte.

Verfasst: Donnerstag 19. Juli 2007, 08:58
von veers
Leonidas hat geschrieben:Die Einheit ist aber dennoch eher noch Terabyte und nicht Terrabyte.
Habe es gesehen zur Kenntnis genommen und gefixt. ;)

Verwende nun KiB/MiB/... :)