Methoden/Komma

Hilfe!! Ich bin im ersten Semsester und ich weiß absolut nich was ich da genau machen soll… Wisst Ihr denn was?

  1. a) Schreiben Sie eine Methode, die eine übergebene Zahl auf- oder abrundet.Beispiele:
    3,2 wird auf 3 abgerundet 3,5 auf 4 aufgerundet
  2. b) Schreiben Sie eine weitere Methode, welche eine übergebene Zahl auf eine bestimmte Anzahl Nachkommastellen rundet. Die Anzahl der Nachkommastellen soll anhand eines zusätzlich übergebenen Parameters bestimmt werden können.

Hinweis: Die Verwendung sämtlicher Methoden aus der Klasse Math ist untersagt!

Ich habe absolut keine Ahnung wie ich das machen soll!!

Könnt Ihr mir bitte Helfen?

Abgesehen von dem obligatorischen Link auf Die 5 1/2 Phasen beim Erschleichen von Lösungen für Aufgaben wird man sicher versuchen, zu helfen, wenn erkennbar ist, dass die „Hilfe“ aus etwas anderem besteht, als daraus, die fertige Lösung zu posten, die du dann nur noch abgeben musst. Der Anfang dafür wären spezifischere Fragen - also, genauer zu sagen woran es hakt.

1 „Gefällt mir“

Ich weiß nicht wie ich das ohne Math lösen soll? Evtl mit einer if Abfrage?

Die Nummer b) kapier ich alleine vom Sinn nicht.

Es geht mir nicht darum eine fertige Aufgabe zu bekommen sondern lediglich einen Hinweis bzw. Tipp, weil ich nicht weiß, wo und wie ich genau starten soll!

Eine Idee könnte sein:

  • die Zahl in einen String umzuwandeln,
  • in diesem String den Dezimalpunkt zu suchen
  • den den Teil vor dem Dezimalpunkt ausschneiden
  • wieder in eine Zahl umwandeln.

bye
TT

@Timothy_Truckle Ooof. Warum sowas empfehlen? Das sollte und würde man in der Praxis ja nicht so machen.

Zum Thema:

„Evtl mit einer if Abfrage“ - ja, gut, es gibt mehrere Wege, wie man das lösen könnte, und eine if-Abfrage könnte darin teilweise vorkommen.

Weißt du, wie man aus einer Zahl wie 3.141 die Zahl 3 machen kann?

In der Praxis würde man die Math.* Methoden verwenden, dass darf der TO aber nicht.

bye
TT

Leider nein…

Ich glaube, unter https://wiki.byte-welt.net/wiki/Gleitkommazahlen_mit_Java_runden steht alles, was du wissen musst.

@Timothy_Truckle Kommt drauf an. Es gibt aber immer wieder Problemstellungen, die zum „einfach(st)en Runden“ sehr ähnlich sind, und bei denen man wissen sollte, wie man das Ziel erreicht. Und … das lernt man … eben indem man sich erstmal überlegt, wie man runden würde, wenn man kein Math hätte. Z.B.: Wie „rundet“ man eine ganze Zahl x so auf, dass sie durch n teilbar ist? Oder wie berechnet man das aufgerundete Ergebnis einer Ganzzahl-Division x/y? Natürlich kann man da mit (int)Math.ceil((double)x/y) rangehen, aber … meh…

Eine mögliche (nicht mathematische) Lösung für die Rundung. Es geht sicher eleganter. Ich bin aber auch kein Informatiker.
Anzahl der Nachkommastellen fehlt noch.

public class MyMath {

   public static int round(double value) {
      int number = (int) value;
      String str = String.valueOf(value);
      char[] chars = str.toCharArray();

      int i = str.indexOf('.');

      if(chars[i+1] > '4') {
         number += 1;
      }

      return number;
   }

   public static void main(String[] args) {
      double number = 9.52;
      System.out.println("MyMath.round("+number+"): " + MyMath.round(number));
   }

}

Auch das mit den Strings. Das macht man doch so nicht :disappointed:

  • Wichtig für’s „Lernen“: Die „direktere“ Variante ist IMHO leichter zu verstehen (toCharArray, indexOf, was?!)
  • Wichtig für die Praxis: Was passiert, wenn man die vorgeschlagende Funktion mit 0.00016 oder so aufruft, ist wohl klar…
  • Auch recht wichtig: Das trägt zu dem Mythos bei, Java sei langsam (oder kompliziert)

Ein kurzer Vergleich:

package bytewelt;

import java.util.Random;

public class RoundingComparison
{
    public static void main(String[] args)
    {
        double min = 0.1;
        double max = 100000.0;
        Random random = new Random(0);
        int runs = 10;
        for (int n = 100; n <= 1000000; n *= 10)
        {
            double array[] = new double[n];
            for (int i = 0; i < n; i++)
            {
                array[i] = min + random.nextDouble() * (max - min);
            }

            long before = 0;
            long after = 0;

            before = System.nanoTime();
            int blackHoleA = 0;
            for (int r = 0; r < runs; r++)
            {
                for (int i = 0; i < array.length; i++)
                {
                    blackHoleA += roundA(array[i]);
                }
            }
            after = System.nanoTime();
            double durationMsA = (after - before) / 1e6;

            before = System.nanoTime();
            int blackHoleB = 0;
            for (int r = 0; r < runs; r++)
            {
                for (int i = 0; i < array.length; i++)
                {
                    blackHoleB += roundB(array[i]);
                }
            }
            after = System.nanoTime();
            double durationMsB = (after - before) / 1e6;
            
            System.out.printf("size %10d durationMsA %8.3fms blackHole %d\n",
                n, durationMsA, blackHoleA);
            System.out.printf("size %10d durationMsB %8.3fms blackHole %d\n",
                n, durationMsB, blackHoleB);
        }
    }
    
    public static int roundA(double value)
    {
        int number = (int) value;
        String str = String.valueOf(value);
        char[] chars = str.toCharArray();

        int i = str.indexOf('.');

        if (chars[i + 1] > '4')
        {
            number += 1;
        }

        return number;
    }

    public static int roundB(double value)
    {
        return (int) (value + 0.5);
    }

}

Ausgabe:

size        100 durationMsA    5,379ms blackHole 54120930
size        100 durationMsB    0,042ms blackHole 54120930
size       1000 durationMsA    3,962ms blackHole 486877950
size       1000 durationMsB    0,266ms blackHole 486877950
size      10000 durationMsA   22,879ms blackHole 692812244
size      10000 durationMsB    0,235ms blackHole 692812244
size     100000 durationMsA  129,318ms blackHole -1507099272
size     100000 durationMsB    3,272ms blackHole -1507099272
size    1000000 durationMsA 1100,618ms blackHole 2105129204
size    1000000 durationMsB    5,279ms blackHole 2105129204

(Das hat jetzt schon was von Cunningham's Law - Meta , aber… falls bibi98 sich das bis hier hin durchgelesen hat, und die Lösung aus dem geposteten Code einfach übernimmt, war es das wohl wert…)

Habs anders gelöst mit einer if Abfrage

Und wenn du deine Lösung postest, macht vielleicht jemand hilfreiche Vorschläge. (Das ist dann eine konstruktive und IMHO befürwortenswerte Form von Cunningham’s Law).

1 „Gefällt mir“

Mach ich morgen, bin jetzt nicht mehr am Rechner

Mit der Nutzung von Double.intValue() kann man den Umweg über die String-Umwandlung vermeiden.

1 „Gefällt mir“
import java.util.Scanner;
public class Kommazahlen {

    public static double runden(double z) 
    	{
        
    	double komma = z % 1;
        
        komma *= 10; 
        
        if (komma < 5.0) 
       
        {
            z = z - (komma / 10);
            
            return z;
            
        } else 
        	
        {
            z = z + (1 -(komma/10));
            
            return z;
        }
    }

    public static void main(String[]args) 
    {
        Scanner scanner = new Scanner(System.in);
        
        System.out.println("Geben Sie die gewünschte Zahl ein: ");
        
        double z = scanner.nextDouble();
        
        System.out.println("Die gerundete Zahl ist: " + runden(z));

    scanner.close();
    
	}

}

Das ist mein Code, allerdings kann ich nicht die Nummer b lösen, da ich nicht genau weiß wie ich die Nachkommastellen ausgeben soll?

Kurz vorneweg: Die Aufgabenstellung sagt erstmal nichts darüber, ob die Zahl vom Benutzer eingegeben werden soll. Vielleicht soll das am Ende so sein (und dann kann man das am Ende auch so abgeben). Aber während man entwickelt, ist es praktisch, wenn man sowas macht wie

    public static void main(String[] args)
    {
        test(0.3);
        test(0.7);
        test(5.3);
        test(5.7);
    }
    private static void test(double z) 
    {
        System.out.println(z + " wird " + runden(z));
    }

Dann brauch man das Programm einfach nur zu starten (und nicht dauernd irgendwas eintippen), und es gibt direkt aus

0.3 wird 0.0
0.7 wird 1.0
5.3 wird 5.0
5.7 wird 6.0

womit man schnell mehrere Fälle gleichzeitig ausprobieren kann, und und auf einen Blick sieht, ob alles stimmt.


Was im Moment in runden gemacht wird, ist etwas komplizierter als es sein müßte, aber schon gar nicht so weit weg, von dem, was man braucht, wenn man das für mehrere Nachkommastellen verallgemeinern will.

Wenn man sich den Code mal anschaut…

public static double runden(double z)
{
    double komma = z % 1;
    komma *= 10;
    if (komma < 5.0)
    {
        z = z - (komma / 10);
        return z;

    }
    else
    {
        z = z + (1 - (komma / 10));
        return z;
    }
}

dann sieht man, wenn man scharf hinschaut: komma wird mit 10 malgenommen, aber das ist nich nötig: Später wird es ja direkt wieder durch 10 geteilt, und bei der if-Abfrage könnte man diesen Faktor auch mit reinrechnen:

public static double runden(double z)
{
    double komma = z % 1;
    if (komma < 0.5)
    {
        z = z - komma;
        return z;

    }
    else
    {
        z = z + (1 - komma);
        return z;
    }
}

Das sieht ja schon ein bißchen einfacher aus.


Ein „Trick“ den man da anwenden kann:

  • Im Moment hast du eine Funktion, die eine Zahl wie 12.345 auf eine ganze Zahl rundet.
  • Was du brauchst ist eine Funktion (z.B. runden(double z, int stellen) die eine Zahl auf eine bestimmte Anzahl Nachkommastellen rundet.
  • Diese Funktion kann man recht einfach implementieren, indem man die schon existierende funktion runden(double z) aufruft

Als Beispiel, wenn es z.B. eine Nachkommastelle sein solle:

  • Mutlipliziere die Eingabe mit 10. Bei einer Eingabe von 12.345 wäre das dann 123.45
  • Wende die runden-Funktion auf diese Zahl an. Das Ergebnis wäre 123.0.
  • Teile diese Zahl durch 10. Das Ergebnis wäre 12.3.

Wenn es mehrere Stellen sein sollen, muss statt 10 etwas anderes verwendet werden. Aber als Tipp: In der Funktion runden(z, stellen) die du schreiben musst, könnte dann eine Zeile wie

double ergebnis = runden(z * faktor) / faktor;

vorkommen…


Ein kleines Gerüst zum Testen:

public static void main(String[] args)
{
    test(12.333, 1);
    test(12.337, 1);
    test(12.377, 1);
    
    test(12.333, 2);
    test(12.337, 2);
    test(12.377, 2);
}

private static void test(double z, int stellen) 
{
    System.out.println(z + " auf " + stellen + " Stellen gerundet "
        + "wird " + runden(z, stellen));
}

Die Ausgabe könnte dann sein

12.333 auf 1 Stellen gerundet wird 12.3
12.337 auf 1 Stellen gerundet wird 12.3
12.377 auf 1 Stellen gerundet wird 12.4
12.333 auf 2 Stellen gerundet wird 12.33
12.337 auf 2 Stellen gerundet wird 12.34
12.377 auf 2 Stellen gerundet wird 12.38
1 „Gefällt mir“
import java.util.Scanner;
public class SechsRundenb {
    
    public static int potenz(int a, int x) {
        int b = 1;
        for (int i = 1; i <= x; i++) {
            b *= a ;
        }return b;
    }
        
    public static double abAufRund(double zahl, int x) {
        int a = 10;
        double neuezahl;
        zahl *= potenz(a, x);
        neuezahl = zahl % 1;
        neuezahl *= 10;
        if (neuezahl < 5) {
            zahl = zahl - (neuezahl / 10);
            zahl = zahl / potenz(a, x);
            return zahl;
        } else {
            zahl = zahl + ( 1 - (neuezahl / 10));
            zahl = zahl / potenz(a, x);
            return zahl;
        }
    }
    
    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        System.out.println("Geben Sie eine Zahl mit Nachkommastellen: ");
        double zahl = scanner.nextDouble();
        System.out.println("Auf wie viele Nachkommastellen soll auf-/abgerundet werden?");
        int x = scanner.nextInt();
        int a = 10;
        System.out.println(abAufRund(zahl, x));
        scanner.close();
    }
}

Habs so gelöst, ist halt sehr lange und umständlich

1 „Gefällt mir“

Hmja. Ich hatte ja gesagt: Du kannst die runden(double z) Funktion, die du schon hattest (!) einfach verwenden, indem du sie in der abAufRund aufrufst.

Da du die Lösung schon hast, hier nur ein Beispiel wie das gleiche (eben in „kürzer“) damit aussehen könnte:

public static double runden(double z, int stellen)
{
    int faktor = potenz(10, stellen);
    return runden(z * faktor) / faktor;
}

Ist doch schön(er)…

1 „Gefällt mir“

Soll die Methode auch für negative Zahlen funktionieren? Wenn ja, solltest du das auch testen.

1 „Gefällt mir“