Java alle Dezimalstellen untereinander bei Konsolenausgabe

estre

Commander
Registriert
Dez. 2005
Beiträge
3.006
Hallo zusammen,

ich hoffe ihr könnt mir bei einem kleinen Java-Problem weiterhelfen.
Und zwar habe ich ein Programm geschrieben, das einige Berechnungen vornimmt und Kommazahlen als Output liefert.

nun hätte ich gerne, dass die jeweiligen Dezimalstellen in der Ausgabe exakt untereinander stehen. Im Moment sieht die Ausgabe noch so aus:
3232,4
3,4
21,3
56,3

Nun hätte ich gerne, dass die Kommas untereinander stehen (und die Zehner, Einer, etc.). Könnt ihr mir da weiterhelfen?

Vielen Dank!
 
Anstatt die Zahlen sofort auszugeben, speicherst Du diese zwischen. Dann ermittelst Du die größte Zahl. Dann kannst wieder über die Zahlen iterieren und für jede Zahl die notwendigen Leerzeichen ausgegeben, damit alles ausgerichtet ist.
 
Ist die Anzahl an Dezimalstellen fest? Also ist es immer nur eine Nachkommastelle, auch bei "x,0"? oder kann es auch "x,xx" und/oder "x,xxxxx" sein?
 
danke für eure Antworten!
@soares: das hört sich sehr kompliziert an ?!

@jurrasstoil: ich habe die Zahlen mit Hilfe der DecimalFormat-Klasse so formatiert, dass immer genau 2 Nachkommastellen erscheinen.
 
@estre Das sind mehrere Arbeitsschritte, die für sich alle sehr einfach umzusetzen sind.

Wenn man eine fixe Breite annimmt, könnte man sich das Ermitteln der Länge der größten Zahl sparen.
 
Mach es mit einer Bedinung.
Zum Beispiel, falls die Zahl >=10 und <100, dann ein String mit 2 Leerzeichen + die Zahl. (Falls die Höchste Zahl im 1000er Bereich ist.)
 
Wenn das Format immer x,xx ist, also auch wenn beide Nachkommastellen 0 sind (x,00), dann ist soares Weg der einfachste. Einfach ([Länge des längsten Wertes] - [Länge des einzurückenden Wertes]) Leerstellen einfügen.

In deinem Beispiel ist der erste Wert mit 6 Zeichen der längste. Die zweite Zahl bekommt also 6 - 3 = 3 Leerzeichen, der dritte bekommt 6 - 4 = 2 Leerzeichen, etc.
 
Zur Ermittlung der Ausrichtung würde ich nur den ganzzahligen Teil betrachten. Ansonsten würde ich eine Prüfung einbauen, um sicher zu stellen, dass auch wirklich immer zwei Nachkommastellen vorhanden sind.

Die Ausgabe würde ich mit System.out.printf machen. Ohne Prüfung zerlegt man die Zahl zur Sicherheit halt noch.
 
Code:
package temp;

import java.util.ArrayList;
import java.util.List;
import java.util.OptionalDouble;
import java.util.regex.Pattern;


public class Test {

	public static void main(String[] args) {
		List<Double> l = new ArrayList<Double>();
		l.add(34.89);
		l.add(5678.09);
		l.add(5.45);
		l.add(0.56);
		List<String> blub = blub(l);
		for(int i=0;i<blub.size();i++){
			System.out.println(blub.get(i));
		}
		}
	
	
	public static List<String> blub(List<Double> l){
		OptionalDouble temp = l.stream().mapToDouble(d -> d).max();
		int longest=0;
		String sTemp = "";
		
		if(temp.isPresent()){
			double asDouble = temp.getAsDouble();
			longest = String.valueOf(asDouble).length();
		}
		List<String> result = new ArrayList<String>();
		
		for(int i=0;i<l.size();i++){
			String[] split = l.get(i).toString().split(Pattern.quote( "." ),2);
			
			sTemp = "";
			for(int j=0; j<longest-split[0].length();j++){
			
				sTemp = sTemp+(" ");
			}
			sTemp = sTemp+split[0]+"."+split[1];
			result.add(sTemp);
		}
		
		return result;
	}

}

Ausgabe siehe Bild.
Keine Garantie für gar nichts und es geht bestimmt viel eleganter, wenn man etwas darüber nachdenkt...
 

Anhänge

  • result.jpg
    result.jpg
    3 KB · Aufrufe: 360
Wenn du mit (wirklich) vielen Zahlen arbeitest, dann sollte man im Code von @MasterOfWar auf jeden Fall noch den String sTemp gegen einen StringBuilder austauschen. Das Konkatenieren von Strings ist recht teuer und wird ordentlich Zeit kosten, wenn man es oft macht. Sähe dann etwa so aus:

Code:
import java.util.ArrayList;
import java.util.List;
import java.util.OptionalDouble;
import java.util.regex.Pattern;
 
 
public class Test {
 
	public static void main(String[] args) {
		List<Double> l = new ArrayList<Double>();
		l.add(34.89);
		l.add(5678.09);
		l.add(5.45);
		l.add(0.56);
		List<String> blub = blub(l);
		for(int i=0;i<blub.size();i++){
			System.out.println(blub.get(i));
		}
	}
	
	
	public static List<String> blub(List<Double> l){
		OptionalDouble temp = l.stream().mapToDouble(d -> d).max();
		int longest=0;
		StringBuilder sTemp = new StringBuilder();
		
		if(temp.isPresent()){
			double asDouble = temp.getAsDouble();
			longest = String.valueOf(asDouble).length();
		}
		List<String> result = new ArrayList<String>();
		
		for(int i=0;i<l.size();i++){
			String[] split = l.get(i).toString().split(Pattern.quote( "." ),2);
			
			for(int j=0; j<longest-split[0].length();j++){
                                sTemp.append(" ");
			}
			sTemp = sTemp.append(split[0]).append(".").append(split[1]);
			result.add(sTemp.toString());
                        sTemp.setLength(0); // Buffer clearen
		}
		return result;
	}
 
}

Das sollte dann bei vielen Zahlen deutlich schneller laufen. Aber man kann da mit Sicherheit noch einiges dran tweaken, wenn Geschwindigkeit wichtig ist.
 
Zuletzt bearbeitet:
also ich muss wirklich sagen, dass ich mir das einfacher vorgestellt habe.
Aber gut, ich werde es morgen mal ausprobieren.

Vielen Dank!
 
Ist jetzt sicherlich nicht gerade die Ideal-Lösung, aber etwas Code braucht es schon. Java ist nicht dafür bekannt, möglichst kompakten Code zu ermöglichen.

Wenn man schon Streams nutzt, kann man das auch durchziehen, also etwa so:

Code:
    public static void main(String[] args) {
        List<Double> numbers = Arrays.asList(34.89, 5678.09, 5.45, 0.563);

        new Test().print(numbers);
    }


    private String format(Double num, int max) {
        ...
    }


    private int length(Collection<Double> numbers) {
        ...
    }


    private void print(Collection<Double> numbers) {
        int length = length(numbers);

        numbers.stream().map(num -> format(num, length)).forEach(System.out::println);
    }
 
War auch erstmal nur eine Idee...hübscher/schneller geht es meistens:
Code:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.regex.Pattern;

public class Test {

	private static String build;

	public static void main(String[] args) {
		List<Double> l = new ArrayList<Double>();
		
		Random r = new Random();
		for(int i=0;i< 100000;i++){
			double randomDouble = 0.0 + (1000000.00 - 0.0) * r.nextDouble();
			l.add(randomDouble);
		}
		printList(fill(l));
		
	}
	
	private static void printList(List<String> temp){
		for (int i = 0; i < temp.size(); i++) {
			System.out.println(temp.get(i));
		}
	}

	public static List<String> fill(List<Double> l) {
		List<String> result = new ArrayList<String>();
		int max = getMax(l);
		for (int i = 0; i < l.size(); i++) {
			double temp = l.get(i);
			String[] split = String.valueOf(temp).split(Pattern.quote("."), 2);
			build = build(split[0], split[1], max);
			result.add(build);
		}
		return result;
	}

	private static int getMax(List<Double> l) {
		double ref = 0.0;
		for (int i = 0; i < l.size(); i++) {
			double temp = l.get(i);
			if (temp > ref) {
				ref = temp;
			}

		}

		String[] split = String.valueOf(ref).split(Pattern.quote("."), 2);
		return split[0].length();
	}

	private static String build(String partOne, String partTwo, int ref) {
		StringBuilder sTemp = new StringBuilder();
		for (int i = 0; i < ref - partOne.length(); i++) {
			sTemp.append(" ");
		}

		return sTemp.append(partOne).append(".").append(partTwo).toString();
	}

}
 
Inzwischen sollte der TE dann eine Idee davon haben, wie das aussehen könnte.
Aber nur weil es so schön ist, dann noch mal ein wenig kürzer. :D

Code:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.regex.Pattern;

public class Test {

	public static void main(String[] args) {
		List<Double> l = new ArrayList<Double>();
		
		Random r = new Random();
		for(int i=0;i< 100000;i++){
			double randomDouble = 0.0 + (1000000.00 - 0.0) * r.nextDouble();
			l.add(randomDouble);
		}
		printList(fill(l));
		
	}
	
	private static void printList(List<String> temp){
                temp.forEach(System.out::println);
	}

	public static List<String> fill(List<Double> l) {
		List<String> result = new ArrayList<String>();
		int max = getMax(l);
		for (int i = 0; i < l.size(); i++) {
			double temp = l.get(i);
			String[] split = String.valueOf(temp).split(Pattern.quote("."), 2);
			result.add(build(split[0], split[1], max));
		}
		return result;
	}

	private static int getMax(List<Double> l) {
		double ref = Collections.max(l);
		String[] split = String.valueOf(ref).split(Pattern.quote("."), 2);
		return split[0].length();
	}

	private static String build(String partOne, String partTwo, int ref) {
		StringBuilder sTemp = new StringBuilder();
		for (int i = 0; i < ref - partOne.length(); i++) {
			sTemp.append(" ");
		}
		return sTemp.append(partOne).append(".").append(partTwo).toString();
	}

}
 
Schon besser. Aber die Library bietet noch andere Funktionen, die man nutzen könnte, anstatt so viel eigenen Code zu produzieren.

Sowas ist schon reichlich umständlich (und ineffizient, wobei das für den TE wohl keine Rolle spielt):

Code:
String[] split = String.valueOf(ref).split(Pattern.quote("."), 2);
return split[0].length();


Das padden ließe sich mittels String#format() in einer Zeile erledigen. Damit würde man build() und fill() komplett einsparen.

Für die Generierung von Zufallszahlen könnte man auch so vorgehen:

Code:
List<Double> numbers = DoubleStream
    .generate(() -> ThreadLocalRandom.current().nextDouble(0, 999))
    .boxed()
    .limit(50)
    .collect(Collectors.toList());


Den Diamond Operator finde ich auch sehr schön.
 
Hallo zusammen,

ich habe mir das ganze nochmal angeschaut und eine einfach Lösung gefunden.
Hier mal ein Beispielcode:
Code:
      double wert1 = 31.9;
		 double wert2 = 313.9;
		 double wert3 = 3313.9;
		 double wert4 = 31233.90;
		 		 
		 System.out.printf(String.format("%15s \n" , wert1));
		 System.out.printf(String.format("%15s \n", wert2));
		 System.out.printf(String.format("%15s \n", wert3));
		 System.out.printf(String.format("%15s \n", wert4));

So funktioniert es einwandfrei.
 
Ist aber "doppelt-gemoppelt". Ein Systemaufruf reicht:

Code:
System.out.printf("%15s \n", wert4);
 
Zurück
Oben