Stellen einer Zahl ermitteln

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

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)
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

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).
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

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.
Das Leben ist wie ein Tennisball.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

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
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

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.
Das Leben ist wie ein Tennisball.
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

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 ;)
Antworten