Variablen Double zwingen Ganzzahlen mit 2 Nachkommastellen auszugeben

Kotelettklopfer

Bekanntes Mitglied
Hallo zusammen,

ich befinde mich seit kurzem im Selbststudium und versuche gerade mein erstes kleines Projekt zu entwickeln.

Kurzfassung:
User gibt diverse Werte ein und Scanner liest diese aus.
Zugewiesen wird in double.

Es handelt sich im Beispiel um Kapital, was bedeutet, es kann auch Komma Beträge geben. INT fällt also für mich raus.
Double zeigt mir die Werte aber nur mit einer Nachkommastelle an. Wie bekomme ich es hin, das er mir wie bei Währungen üblich zwei Kommastellen ausgibt.

Beispiel:


Kapital wird 2000,25 eingegeben -> double gibt aus 2000.25
Kapital wird 2000 eingegeben -> double gibt 2000.0 aus.. <- Hier soll er 2000.00 ausgeben.


Jemand eine Idee?

Danke Euch

VG
Kotelettklopfer
 
Für mich als Laien fiel INT raus, weil es doch nur für Ganzzahlen ist?

Und als Ausgabe möchte ich schon die Summe in Euro und nicht in Cent. Ginge das nicht?

Vielleicht einfacher mein Noob Projekt zu verstehen 🙂

import java.util.Scanner;

public class Zinsrechner {

public static void main(String[] args) {
// TODO Auto-generated method stub

/* Zinsrechner mit frei wählbaren Werten
* In Klärung -> Ganzzahl in double mit 2 Nachkommastellen anzeigen */


Scanner scanner = new Scanner(System.in);
System.out.println("Geben Sie Ihr Kapital an");
double capital = scanner.nextDouble();
System.out.println("Bitte geben Sie den Zinssatz Ihrer Bank ein");
double interestRate = scanner.nextDouble();
System.out.println("Bitte geben Sie die gewünschte Anlagedauer in Monaten an");
int month = scanner.nextInt();
double totalInterestRate = capital * interestRate * month / (12*100);
double capitalTotal = capital * interestRate * month / (12*100) + capital;

System.out.println("Berechnung:");
System.out.println("Ihr Startkapital: " + capital + "€");
System.out.println("Zinssatz: " + interestRate + "%");
System.out.println("Anlagedauer: " + month + "Monate");
System.out.println("Zinsen über die gesamte Laufzeit: " + totalInterestRate + "€");
System.out.println("Kapital nach " + month + " Monaten: " + capitalTotal + "€");
}
 
Zuletzt bearbeitet:
Ja, aber du kannst Beträge ja in 1/100tel angeben. Das Problem bei Gleitkommazahlen ist, dass diese einfach nicht genau sind. Und sobald Du damit rechnest werden Ungenauigkeiten immer größer.

Ein einfaches kleines Beispiel:
Java:
        double value = 0.01;
        double sum = 0.0;
        for (int i=0; i<1000; i++)
            sum += value;

        System.out.println(sum);

Da müsste ja dann 10 rauskommen ... lass es laufen und staune 🙂

Das Problem ist halt, dass nicht alle Werte des Dezimalsystems im Binären System genau dargestellt werden können. 0.01 ist so ein Wert ...

Daher ist Double nicht tauglich, denn solche Probleme möchte man nicht wirklich haben.

Neben der Verwendung von int gibt es auch noch andere Möglichkeiten:
- BigDecimal
- JavaMoney Library https://javamoney.github.io/

Ansonsten das eigentliche Problem von Dir: Du willst eine spezielle Formatierung der Ausgabe. Da ist dann z.B. NumberFormat nützlich.
 
Alternative: BigDecimal (für beliebig grosse Zahlen) + NumberFormat in Deutscher Locale für vernünftige Ausgaben:
Java:
import java.math.*;
import java.text.NumberFormat;
import java.util.*;
public class Zinsenrechner {
  public static void main(String[] args) {
    NumberFormat pf = NumberFormat.getPercentInstance(Locale.GERMANY);
    NumberFormat cf = NumberFormat.getCurrencyInstance(Locale.GERMANY);
    Scanner scanner = new Scanner(System.in);
    System.out.println("Geben Sie Ihr Kapital an");
    BigDecimal capital = new BigDecimal(scanner.nextLine());
    System.out.println("Bitte geben Sie den Zinssatz Ihrer Bank ein");
    BigDecimal interestRate = new BigDecimal(scanner.nextLine());
    System.out.println("Bitte geben Sie die gewünschte Anlagedauer in Monaten an");
    int month = scanner.nextInt();
    BigDecimal totalInterestRate = 
        capital.multiply(interestRate)
               .multiply(BigDecimal.valueOf(month))
               .divide(BigDecimal.valueOf(12*100), RoundingMode.HALF_UP);
    BigDecimal capitalTotal = 
        capital.multiply(interestRate)
               .multiply(BigDecimal.valueOf(month))
               .divide(BigDecimal.valueOf(12*100), RoundingMode.HALF_UP)
               .add(capital);
    System.out.println("Berechnung:");
    System.out.println("Ihr Startkapital: " + cf.format(capital));
    System.out.println("Zinssatz: " + pf.format(interestRate));
    System.out.println("Anlagedauer: " + month + " Monate");
    System.out.println("Zinsen über die gesamte Laufzeit: " + cf.format(totalInterestRate));
    System.out.println("Kapital nach " + month + " Monaten: " + cf.format(capitalTotal));
  }
}
 
Ich danke Euch. Ich schaue mir mal den Code von httpdigest genauer an.
Zur Zeit verstehe ich noch nicht ganz was da passiert (gerade im Bereich der Berechnungen) aber das wird sich schon klären 🙂

Danke !!!
 
Die BigDecimal Berechung habe ich nun selbst noch einmal geschrieben und soweit verstanden.
Funktioniert soweit Prima. Danke !!!

Es gab/gibt nur 2 kleine Probleme:

1. Zeile 26 "System.out.println("Zinssatz: " + pf.format(interestRate));" Gibt bei Eingabe von 2.5 den Wert 250% aus.
Ich hab es ganz pragmatisch gelöst, indem ich hier einfach ohne das pfFormat gearbeitet habe.
"System.out.println("Zinssatz: " + interestRate + "%")"
Gibt es hier noch eine Lösung?

2. Java verlangt hier ja einen Punkt anstelle eines Kommas. Der User bekommt also wenn er es so eintippen würde (2,5) ein Problem.
Er muss zwingend 2.5 eintippen. Kann man das noch anders steuern oder muss man hier dem User klare Vorgaben machen wie er es einzutippen hat?


Danke Euch 🙂
 
Erst einmal zum Verständnis: Wie etwas dargestellt wird, wird über "Locale" Einstellungen definiert. Diese sind von Land zu Land oft unterschiedlich und gibt so Dinge vor wie Dezimal-Trenner und so.

Diese Einstellungen kann man nutzen z.B. per NumberFormat:
Java:
        NumberFormat format = NumberFormat.getInstance(Locale.GERMAN);
        Number number = format.parse("1,234");
        double d = number.doubleValue();

Du kannst die Einstellung des Users verwenden, also die getInstance Methode ohne Parameter aufrufen. Das hat den Vorteil dass Du das Format nicht vorgibst. Jemand mit US Settings wird wie gewohnt ein . eingeben. Jemand in DE hat sein , bei seinen Eingaben ...
 
Mein kleines "Programm" hat nun den ersten Status erreicht.
Was mir noch garnicht gefällt, ist die Lesbarkeit. Leider wusste ich nicht wie man Logik von Optik trennt. Daher ist alles in einer Klasse.
Der logische Part wurde in Eclipse geschrieben und die GUI im Java Editor. Das nachher zusammenfügen, hatte mich nerven gekostet xD.

Was denkt ihr? Geht das so für das erste Programm nach einer Lernezeit im Selbststudium von knapp 2 Monaten?

ToDo für dieses Lernprojekt:

- Lernen von Trennung Logik / Optik
- Lernen Variable auch außerhalb der eigenen Methode nutzen zu können (return) -> Hätte gern im Label für die Ergebnisse immer auch die Monate anstatt ein X stehen gehabt. Kam aber an die Variable nicht ran..


 
Mh, fangen wir mal hinten an. Namen. Namen sind wichtig. Du gehst sehr freizuegig mit der Namensgebung um, was nicht so gut ist. Gibt deinen Variablen und Objekten immer klingende Namen und achte darauf dass diese immer konsistent sind. Versuche nicht sowas wie Ungarische Notation halbherzig abzubilden, das wird nichts. Nicht mal komplett "richtig" gemacht ist Ungarische Notation wirklich hilfreich. Viel besser ist wenn du dir gute und klingende Namen angewoehnst welche leicht zu lesen sind, zum Beispiel "interestRateLabel", "calculateButton" und so weiter. Im selben Sinne, entscheide dich fuer eine Sprache und bleibe dabei, mische nicht Sprachen in den Variablennamen. Am besten du nimmst die Domaenensprache, also in dem Fall haette ich Deutsch gesagt, und verwendest diese. Die Domaenensprache zu verwenden ist auch sehr wichtig um zu vermeiden dass es am Ende drei unterschiedliche Woerter fuer das selbe gibt, zum Beispiel "amount", "value" und "capital" das gleiche meinen, naemlich den Betrag welcher eingegeben wurde und auf welchem berechnet wird. Sehr schoenes Bespiel ist heir "Laufzeit", du hast dich fuer "runtime" entschieden aber "term" waere vermutlich richtiger. Also bleib einfach in der Domaenensprache und du hast das Problem nie (Variable heiszt "laufzeit"). Und kuerze Namen nicht ab nur weil du kannst oder "Tippfaul" bist, schreibe Namen immer aus. Weil wenn du mal mehr Code schreibst und du dann Zeilen hast wie "bt = dd * m" wirst du Spasz haben.

Das setzen von Groesze und Farben in Swing ist mit Vorsicht zu genieszen, aus dem simplen Grund dass du nichts ueber das Zielsystem weiszt. Swing unterstuetzt unterschiedliche Look and Feels welche je nach Platform oder je nach gewaehlten LaF anders aussehen und sich eventuell sogar anders verhalten. Also die fixe Groesze von deinem Frame ist zum Beispiel auf einem HiDPI System etwas schlecht. Versuche hier immer auf dynamischere Layouts zu gehen welche sich frei vergroeszern udn verkleinern koennen, zum Beispiel das "BorderLayout" und so weiter.

BigDecimal ist hier genau richtig. Perfekt.

"String.valueOf" ist unnoetig wenn du bereits einen String hast. Wenn du einen "StringBuffer", "StringBuilder" bekommst, kannst du auch direkt darauf "toString", was die Zeile etwas klarer macht.

Du machst im Moment in deinem Frame Konstruktor Dinge die besser in die "main" Methode passen wuerden, zum Beispiel das setzen von der CloseOperation und das anzeigen selbst. Denke von deinem Fenster etwas loesgeloester von der "main" Logik, weil was wenn du zwei davon anzeigen willst zum Beispiel. Also besser dass das Fenster nur Fenster ist, und sich die "main" darum kuemmert dass dieses angezeigt wird.
 
Mh, fangen wir mal hinten an. Namen. Namen sind wichtig. Du gehst sehr freizuegig mit der Namensgebung um, was nicht so gut ist. Gibt deinen Variablen und Objekten immer klingende Namen und achte darauf dass diese immer konsistent sind. Versuche nicht sowas wie Ungarische Notation halbherzig abzubilden, das wird nichts. Nicht mal komplett "richtig" gemacht ist Ungarische Notation wirklich hilfreich. Viel besser ist wenn du dir gute und klingende Namen angewoehnst welche leicht zu lesen sind, zum Beispiel "interestRateLabel", "calculateButton" und so weiter. Im selben Sinne, entscheide dich fuer eine Sprache und bleibe dabei, mische nicht Sprachen in den Variablennamen. Am besten du nimmst die Domaenensprache, also in dem Fall haette ich Deutsch gesagt, und verwendest diese. Die Domaenensprache zu verwenden ist auch sehr wichtig um zu vermeiden dass es am Ende drei unterschiedliche Woerter fuer das selbe gibt, zum Beispiel "amount", "value" und "capital" das gleiche meinen, naemlich den Betrag welcher eingegeben wurde und auf welchem berechnet wird. Sehr schoenes Bespiel ist heir "Laufzeit", du hast dich fuer "runtime" entschieden aber "term" waere vermutlich richtiger. Also bleib einfach in der Domaenensprache und du hast das Problem nie (Variable heiszt "laufzeit"). Und kuerze Namen nicht ab nur weil du kannst oder "Tippfaul" bist, schreibe Namen immer aus. Weil wenn du mal mehr Code schreibst und du dann Zeilen hast wie "bt = dd * m" wirst du Spasz haben.

Das setzen von Groesze und Farben in Swing ist mit Vorsicht zu genieszen, aus dem simplen Grund dass du nichts ueber das Zielsystem weiszt. Swing unterstuetzt unterschiedliche Look and Feels welche je nach Platform oder je nach gewaehlten LaF anders aussehen und sich eventuell sogar anders verhalten. Also die fixe Groesze von deinem Frame ist zum Beispiel auf einem HiDPI System etwas schlecht. Versuche hier immer auf dynamischere Layouts zu gehen welche sich frei vergroeszern udn verkleinern koennen, zum Beispiel das "BorderLayout" und so weiter.

BigDecimal ist hier genau richtig. Perfekt.

"String.valueOf" ist unnoetig wenn du bereits einen String hast. Wenn du einen "StringBuffer", "StringBuilder" bekommst, kannst du auch direkt darauf "toString", was die Zeile etwas klarer macht.

Du machst im Moment in deinem Frame Konstruktor Dinge die besser in die "main" Methode passen wuerden, zum Beispiel das setzen von der CloseOperation und das anzeigen selbst. Denke von deinem Fenster etwas loesgeloester von der "main" Logik, weil was wenn du zwei davon anzeigen willst zum Beispiel. Also besser dass das Fenster nur Fenster ist, und sich die "main" darum kuemmert dass dieses angezeigt wird.
Danke Dir für die ausführliche Erklärung. Werde mich in Zukunft etwas mehr auf die angesprochenen Dinge fokusieren. Denke das sind Sachen, die kommen dann auch mit der Zeit. Irgendwann hat man seine eigene Vorgehensweise, was Namensgebung betrifft.
Jetzt war ich nach der kurzen Zeit und dem ein oder anderem Tip hier, stolz das erste Programm am laufen zu haben xD
 

Neue Themen


Zurück
Oben