Seite 2 von 2

Verfasst: Dienstag 13. Oktober 2009, 09:15
von b.esser-wisser
Was schneller ist, sollte sich ja rausfinden lassen:

Code: Alles auswählen

#! /usr/bin/env python
# coding:utf-8

from __future__ import division
from timeit import Timer

REPEATS = 30000
# test, preparation, title
LOG10 = "int(log10( {0} )) + 1", "from math import log10", "log:"
LEN_STR = "len(str( {0} ))", "", "len-str:"

def main():
    for i in (1, 1000, 1000000, 10**9, 2**50, 2**100):
        print u"Zahl = {0}".format(i)
        for test in (LOG10, LEN_STR):
            t = Timer(test[0].format(i), test[1]).timeit(REPEATS)
            print "{0:8}{1:12.6f}".format(test[2], t)
        # Test:
        #~ from math import log10
        #~ t = eval (LOG10[0].format(i) + " == " + LEN_STR[0].format(i))
        #~ print t
if "__main__" == __name__: main()
Andererseits ist die Fragestellung nicht besonders interessant, meistens gibt man ja die Länge bei den Feldern (string-formatting , str.format()) oder der Zeilenlänge an (textwrap)
hth, Jörg (der sich endlich mit str.format auseinandergesetzt hat)

Verfasst: Dienstag 13. Oktober 2009, 10:30
von numerix
b.esser-wisser hat geschrieben:Andererseits ist die Fragestellung nicht besonders interessant, meistens gibt man ja die Länge bei den Feldern (string-formatting , str.format()) oder der Zeilenlänge an (textwrap)
Kommt drauf an, was man vorhat. Es gibt durchaus Problemstellungen, wo die Anzahl der Ziffern einer Zahl benötigt wird, wobei man ehrlicherweise sagen muss, dass die Anzahl der Stellen der Binärdarstellung dabei eher von Interesse ist. Wobei man dann wiederum sagen könnte, dass das eigentlich das gleiche in grün ist - len(bin(n)-2) oder int(log(n,2)+1) - , wenn es nicht mit Python 3.1 die Methode bit_length() gäbe:

Code: Alles auswählen

>>> n = 1000
>>> int(log(n,2)+1)
10
>>> len(bin(n))-2
10
>>> n.bit_length()
10
Dabei ist die bit_length()-Methode mit Abstand am schnellsten, und zwar fast unabhängig von der Größe der Zahl. Der log() ist (auf meinem Rechner) 4x langsamer, aber ebenfalls nahezu unabhängig von der Größe der Zahl. Die Variante über bin() ist für kleinere Zahlen schneller als log(), wird ab einer bestimmten Zahlengröße aber unbrauchbar (weil zu langsam).

Verfasst: Dienstag 13. Oktober 2009, 15:06
von EyDu
derdon hat geschrieben:Dein Snippet (und auch meines) ist rekursiv, nicht iterativ
Ach was. Ich habe nie etwas anderes behauptet. Nur das eine iterative Lösung kürzer ist als die von str1442.

Deine 46 Zeichen ist übrigens exakt meine (Vorgeschlagene) Variante.

Verfasst: Dienstag 13. Oktober 2009, 15:33
von numerix
EyDu hat geschrieben:Deine 46 Zeichen ist übrigens exakt meine (Vorgeschlagene) Variante.
Es geht auch kürzer (36 Zeichen).

Code: Alles auswählen

c=lambda n:1+c(abs(n)/10)if n else 0

Verfasst: Dienstag 13. Oktober 2009, 15:49
von EyDu
Sehr hübsch, so spart man sich das nervige Zwischenspeichern des Quotienten. Ob man bei n=0 eine 0 oder eine 1 erhalten möchte ist natürlich ein wenig anwendungsabhängig.

Verfasst: Dienstag 13. Oktober 2009, 19:23
von str1442
Und gleich viel kürzer als eine einfache iterative Lösung ^^
Ich sag ja, die Lösung in der Form ist ziemlicher Quatsch (hatte gestern Nacht noch an dem Posting rumeditiert). Aber sie ist auf jeden Fall besser ist als einfach global mit einer entsprechenden Variable zu benutzen. Und für andere, global-heraufbeschwörende Probleme kann eine solche Form (neben typischen anderen Lösungen) recht nützlich sein ;)