# Länge eines long wertes



## Jenny (4. Aug 2009)

Hallo,

ich würde gern die "Länge" von long-Werten ermitteln. Mit Länge meine ich die Anzahl der Dezimalstellen. Gibt es da eine performantere Lösung als den Long in einen String umzuwandeln und dann die Länge zu ermitteln?

schönen gruss


----------



## tfa (4. Aug 2009)

DU könntest ganz viele if-else-Abfragen machen (also [c]if (l<10) return 1; else if (l<100) return 2; ...[/c]) oder du castest den long-Wert in ein double und berechnest den 10er-Logarithmus. Keine Ahnung, was am schnellsten ist.


----------



## B4RC0D3 (4. Aug 2009)

also da eher


```
long zahl;
int stellen=1;
while(zahl>10)
{
stellen+=1;
zahl=zahl/10;
}
```

/edit
oh das mit der performance hab ich nicht gesehen....
da ist meines schlechter.....


----------



## faetzminator (4. Aug 2009)

oder so eine Bastelei:

```
int c = 1;
while ((l = l / 10.0) > 1.0) {
    c++:
}
```

Edit: ach B4RC0D3 war schneller


----------



## Ark (4. Aug 2009)

Die einfachste Lösung:

```
Math.ceil(Math.log10(x)) // ab 1.5
Math.ceil(Math.log(x) / Math.log(10)) // bis vor 1.5
```
Für Zahlen kleiner oder gleich 0 muss man aber etwas tricksen.

Ark


----------



## Paddelpirat (4. Aug 2009)

Will auch noch eine Schleife einwerfen 


```
long zahl;
int stellen = 0;
		
do {
	stellen++;
} while((zahl = zahl / 10) != 0);
```

Oder wenns einfach gehen soll:


```
String.valueOf(zahl).length();
```

Wobei du bei negativen Zahlen entscheiden müsstest, ob das Minus-Zeichen mitgezählt wird oder nicht.


----------



## Jenny (4. Aug 2009)

Danke für die vielen und schnellen Antworten! Werte unter Null kommen bei mir nicht vor (sind zeiten). Ich werde mal eine simple messung machen und euch berichten!


----------



## Jenny (4. Aug 2009)

Also, für diejenigen, die es interessiert. B4RC0D3 hatte mit seiner einschätzung recht. Die Schleifen-Lösung ist eindeutig am langsamsten (ca. Faktor 2). length() und Logarithmus nehmen sich kaum was (bei meiner messung war length() ein bißchen schneller.  

Nochmals Danke, und schönen gruß!


----------



## Marco13 (4. Aug 2009)

Dann hatten' wir's jetzt ja auch nochmal für long  http://www.java-forum.org/java-basics-anfaenger-themen/65207-laenge-eines-integers-ermitteln.html


----------



## Paddelpirat (4. Aug 2009)

Mag sich mal Jemand diese Lösung anschauen?


```
stellen = 0;
		
long a = 1, b, c;
		
do {
	stellen++;
	b = a << 3;
	c = a << 1;
	a = b+c;
}
while(a <= zahl && a>0);
```

Ich hab sie mal bei mir getestet und wenn ich mich nicht mit meiner Zeitmessung vertan habe müsste diese Lösung noch schneller sein. (Sogar schneller als wenn man a immer mit 10 multiplizieren würde). In dem anderen Thread stand ja auch dass Dividieren sehr "teuer" ist, daher dieser Ansatz...

Edit:

Falls es jemanden interessiert sind hier die Ergebnisse mit dem TestProgramm aus dem anderen Thread:

sum: 69000000, time: 1672
sum: 69000000, time: 1069
sum: 69000000, time: 212 //if-else
sum: 69000000, time: 1698
sum: 69000000, time: 635 //shift-operator
sum: 69000000, time: 1751
sum: 69000000, time: 1102
sum: 69000000, time: 206 //if-else
sum: 69000000, time: 1687
sum: 69000000, time: 736 //shift

und hier die Shift-Lösung nochmal etwas schöner ohne b und c:

```
stellen = 0;		
long a = 1;
		
do {
	stellen++;
	a = ((a << 3) + (a << 1));
}
while(a <= zahl && a>0);
```

Edit2: Hab gerade noch festgestellt, dass die if-else Anweisung bei richtigen Longs explodiert. Hier die Ergebnisse:

sum: 204000000, time: 7933
sum: 204000000, time: 4845
sum: 204000000, time: 21205 //if-else
sum: 204000000, time: 7791
sum: 204000000, time: 4650 //shift
sum: 204000000, time: 7939
sum: 204000000, time: 4854
sum: 204000000, time: 21123 //if-else
sum: 204000000, time: 7819
sum: 204000000, time: 4753 //shift

Dazu habe ich noch folgende Test-Fälle aufgerufen:
            sum += worker.calc(new Long("10000000000000"));
            sum += worker.calc(new Long("100000000000000"));
            sum += worker.calc(new Long("1000000000000000"));


----------



## Ark (4. Aug 2009)

Das sieht bisher sehr schnell aus. Genial. oO

Ob man da noch etwas rausholen kann, indem man vorpartitioniert?

```
if(zahl<1000000000){
	if(zahl<10000){
		// 0 bis <10000
	}
	else{
		// 10000 bis <1000000000
	}
}
else{
	if(zahl<10000000000000){
		// 1000000000 bis <10000000000000
	}
	else{
		// 10000000000000 bis MAX_VALUE
	}
}
```
Ark


----------



## Paddelpirat (5. Aug 2009)

Kleine Korrektur noch ... if-else bleibt auch bei den longs schneller, allerdings musste ich in dem Test dafür sowas noch anlegen:

```
static long a = new Long("10000000000");
    static long b = new Long("100000000000");
    static long c = new Long("1000000000000");
    static long d = new Long("10000000000000");
    static long e = new Long("100000000000000");
    static long f = new Long("1000000000000000");
    static long g = new Long("10000000000000000");
    static long h = new Long("100000000000000000");
    static long j = new Long("1000000000000000000");
```
und anschließend if(i < a) etc abfragen... sieht insgesamt hässlich aus, aber scheint die schnellste Lösung zu sein.

@Ark Das (Durchschnitts-)Ergebnis von if-else könnte man bestimmt noch durch "divide & conquer" verbessern, kannst es ja mal ausprobieren


----------



## Marco13 (5. Aug 2009)

Sowas wie
static long a = new Long("10000000000");
sollte nicht notwendig sein. 
static long a = 10000000000L;
sollte gehen (das "L" am Ende ist das wichtige - ansonsten kommt die Meldung "...constant too large", was du vermutlich mit dem "new Long" zu vermeiden versucht hast)


----------



## Paddelpirat (5. Aug 2009)

Aso, gut zu wissen. Ich benutz die nicht allzu oft, fand nur das Thema interessant *g*.


----------

