Java Russische Bauernmultiplikation aufgabe

Hallo zusammen,
ich muss ein Programm schreiben (Russische Bauernmultiplikation). An sich klappt alles, ich weiß jedoch nicht, wie ich die Anzahl der „----“ und „====“ so variiere, dass es mit der länge vom Ergebnis identisch ist. Mit zweistelligen Zahlen passt das, aber sobald einstellige Zahlen miteinander multipliziert werden sollen verschiebt sich natürlich alles. Z.b. ist die rechte „6“ dann nicht auf selber höhe wie die untere „6“ und das gleiche mit dem Ergebnis. Ich habe auch schon versucht das Problem mit printf statt println zu lösen, jedoch muss man da ja auch den Abstand angeben, z.B. %6d, der wiederum auch variiert.
BMP0
BMP1
BMP2
(Siehe Anhang: Bild 1 & 2 ist mein Ergebnis und es soll so sein wie Bild 3)
Danke für jede Hilfe und hier ist mein Code =)

Ich weiß leider nicht, wie mein übersichtlich den Code einfügt, tut mir leid :slight_smile:

import java.util.Scanner;

public class Bauernmultiplikation {
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        int num1 = Integer.parseInt(args[0]);
        int num2 = Integer.parseInt(args[1]);
        int laenge = String.valueOf(num1).length() + 5 + String.valueOf(num2).length();

        printBoard(num1,num2);
        int result = multipliziere(num1,num2);
        int resultLength = Integer.toString(result).length();
        System.out.println();

        for(int i = 0; i < laenge - resultLength;i++)
            System.out.print(" ");
        System.out.print(result);

    }

    private static void printBoard(int num1, int num2) {
       int laenge2 = String.valueOf(num1).length() + 5 + String.valueOf(num2).length();
        System.out.printf("%1d %1s %1d \n" ,num1,"*",num2);
            for(int i = 0; i< laenge2;i++)
                System.out.print("-");
        System.out.println();
        while(num1>=1) {

           if(num1 % 2 == 0)
              System.out.printf("%2d %6d %s \n", num1, num2, "X");
          else
               System.out.printf("%2d %6d \n", num1, num2);
            num1/=2;
            num2*=2;
        }
        for (int j = 0; j < laenge2;j++)
            System.out.print("=");
    }

    private static int multipliziere(int x, int y){

        if(x==1)
            return y;

        if(x%2!=0)
            return y + multipliziere(x/2, y*2);
        else
            return multipliziere(x/2, y*2);

    }

}

Um hier code zu posten, kann man dreifache Backticks verwenden:

```
Hier der Code
```

Damit bleiben Einrückung und Formatierung erhalten.

Und … um Einrückung und Formatierung geht’s hier ja :smiley:

Ich habe auch schon versucht das Problem mit printf statt println zu lösen, jedoch muss man da ja auch den Abstand angeben, z.B. %6d, der wiederum auch variiert.

Auch diesen „variablen Teil“ kann man … mit einer Variablen beschreiben:

int wieBreit = 8;
String format = "%" + wieBreit + "d";
System.out.printf(f, 123);

Damit wird die angegebene Zahl „so breit“ ausgegeben, wie es mit wieBreit angegeben ist.


Damit könntest du die Lösung schon hinbekommen. Aber … es könnte etwas fummelig sein. Das schwierige ist wohl, die richtigen Längen hinzubekommen (und ich nehme an, dass das einer der wichtigsten Teile der Aufgabe ist - wenn nicht sogar genau das, worum es in der Aufgabe eigentlich geht).

Wurde diese „Einrückung“ und „Formatierung“ in der Aufgabenstellung genauer beschrieben?

(Der Punkt ist: Man muss ein bißchen aufpassen, dass man nicht etwas macht, so dass die Formatierung bei gleichlangen Zahlen (wie 36 * 36) zwar richtig ist, sie aber bei unterschiedlich langen Zahlen (wie z.B. 12 * 12345 oder 12345 * 12) auf einmal falsch wird…)

Hey, erst einmal danke für deine Antwort :smiley:

Auch diesen „variablen Teil“ kann man … mit einer Variablen beschreiben:

Genau das habe ich ja versucht. Ich hab die länge des Strings von „36 * 36“ z.B. in einer Variable gespeichert, jedoch wird es schwierig, wie du schon gesagt hast, wenn es unterschiedlich lange zahlen sind verschiebt sich ja alles.

Wurde diese „Einrückung“ und „Formatierung“ in der Aufgabenstellung genauer beschrieben?

Tatsächlich nicht. Ich hänge die Aufgabenstellung gerne dran.

(Der Punkt ist: Man muss ein bißchen aufpassen, dass man nicht etwas macht, so dass die Formatierung bei gleichlangen Zahlen (wie 36 * 36 ) zwar richtig ist, sie aber bei unterschiedlich langen Zahlen (wie z.B. 12 * 12345 oder 12345 * 12 ) auf einmal falsch wird…)

Also ich habe bis jetzt nur hinbekommen, dass es mit zwei gleichstelligen Zahlen funktioniert. (z.B. 6 * 6 oder 36 * 36). Aber ich schaff es nicht ein Programm zu schreiben, dass beides kann bzw. sogar 12 * 12345.
Ich wäre wirklich dankbar, wenn du mir weiterhelfen könntest, sitze an der Aufgabe ewig dran :slight_smile:

Hmja. Man muss sich halt überlegen, wie breit die „Spalten“ am Ende sein müssen. Die rechte Spalte muss ggf. so breit sein, dass sie praktisch das ganze Ergebnis enthalten kann. Die linke aber nur so breit, wie die erste Zahl.

In der Aufgabenstellung ist von „Formatierung“ aber nichts gesagt. Deswegen würde ich annehmen, dass die Formatierung keine Rolle spielt und auch nicht bewertet wird, und das ganze auch einfach flach ausgeben werden könnte, wie etwa

36 und 36, gerade
18 und 72, gerade
...
Ergebnis: 1296

Oder anders: Wenn bei einem IT-Projekt etwas implementiert werden soll, muss das explizit als Anfrorderung genannt sein.

Wie auch immer, hier mal ein Beispiel

package bytewelt;

public class BauernmultiplikationFinal
{
    public static void main(String[] args)
    {
        runTest(6, 6);
        runTest(36, 36);
        runTest(12, 34567);
        runTest(12345, 67);
    }

    private static void runTest(int num1, int num2)
    {
        int result = multipliziere(num1, num2);
        printBoard(num1, num2, result);
    }

    private static void printBoard(int num1, int num2, int result)
    {
        int lenA = String.valueOf(num1).length();
        int lenB = String.valueOf(result).length();
        int lenTotal = lenA + 3 + lenB;
        System.out.printf("%" + lenA + "d * %" + lenB + "d \n", num1, num2);
        System.out.println(nTimes("-", lenTotal));
        while (num1 >= 1)
        {
            if (num1 % 2 == 0)
                System.out.printf("%" + lenA + "d   %" + lenB + "d X \n", num1,
                    num2);
            else
                System.out.printf("%" + lenA + "d   %" + lenB + "d \n", num1,
                    num2);
            num1 /= 2;
            num2 *= 2;
        }
        System.out.println(nTimes("=", lenTotal));
        System.out.printf("%" + lenTotal + "d\n", result);
    }

    private static String nTimes(String s, int n)
    {
        String result = "";
        for (int i = 0; i < n; i++)
        {
            result += s;
        }
        return result;
    }

    private static int multipliziere(int x, int y)
    {

        if (x == 1)
            return y;

        if (x % 2 != 0)
            return y + multipliziere(x / 2, y * 2);
        else
            return multipliziere(x / 2, y * 2);

    }

}

Es gibt wohl sinnvollere Sachen, die man lernen kann, als die Frage, wie man printf geschickt einsetzt.

Hi,
vielen Dank für deine ausführliche Erklärung!!!

In der Aufgabenstellung ist von „Formatierung“ aber nichts gesagt. Deswegen würde ich annehmen, dass die Formatierung keine Rolle spielt und auch nicht bewertet wird, und das ganze auch einfach flach ausgeben werden könnte, wie etwa

Nach Absprache mit meinem Dozenten, ist in der Aufgabenstellung die Schwierigkeit tatsächlich die Formatierung.

Danke, dass du dir die Mühe gemacht hast, den Code zu schreiben, jedoch ist da auch der Fehler, dass beim Beispiel 36 die Formatierung so aussehen soll : „36 * 36“, jedoch kommt im Programm dann „36 * 0036“ (Die 0 soll die Leerzeichen visualisieren).
Vor und nach dem „*“ muss jeweils ein Leerzeichen rein und die Tabelle sollte sich demnach anpassen. Kennst du vielleicht noch eine Weg, wie ich das erreiche?

Mfg

Wenn sich die Gelegenheit ergibt, sag’ deinem Dozenten mal, dass man in der IT Anforderungen explizit machen und vernünftig spezifizieren muss. Und auch das müssen IT-Leute lernen. Nah, vielleicht nicht wenn man Dozent werden will, aber sonst schon. Ja, " :grin: " - das klingt ein bißchen fies, aber … es gibt den schönen Satz

Walking on water and developing software from a specification are easy if both are frozen.
Edward V. Berard

In diesem Sinne hat die folgende Klasse absichtlich einen Namen, der darauf hindeutet: „Irgendwas stimmt da mit dem Entwicklungsprozess nicht…“:

public class BauernmultiplikationFinal2
{
    public static void main(String[] args)
    {
        runTest(6, 6);
        runTest(36, 36);
        runTest(12, 34567);
        runTest(12345, 67);
    }

    private static void runTest(int num1, int num2)
    {
        int result = multipliziere(num1, num2);
        printBoard(num1, num2, result);
        System.out.println();
    }

    private static void printBoard(int num1, int num2, int result)
    {
        int lenA = String.valueOf(num1).length();
        int lenB = String.valueOf(num2).length();
        int lenTotal = lenA + 3 + lenB;
        System.out.printf("%" + lenA + "d * %" + lenB + "d \n", num1, num2);
        System.out.println(nTimes("-", lenTotal));
        while (num1 >= 1)
        {
            if (num1 % 2 == 0)
                System.out.printf("%" + lenA + "d %" + (lenB + 2) + "d X \n", num1,
                    num2);
            else
                System.out.printf("%" + lenA + "d %" + (lenB + 2)  + "d \n", num1,
                    num2);
            num1 /= 2;
            num2 *= 2;
        }
        System.out.println(nTimes("=", lenTotal));
        System.out.printf("%" + lenTotal + "d\n", result);
    }

    private static String nTimes(String s, int n)
    {
        String result = "";
        for (int i = 0; i < n; i++)
        {
            result += s;
        }
        return result;
    }

    private static int multipliziere(int x, int y)
    {

        if (x == 1)
            return y;

        if (x % 2 != 0)
            return y + multipliziere(x / 2, y * 2);
        else
            return multipliziere(x / 2, y * 2);

    }

}

Das ist zwar Gefrickel, aber die Ausgabe fürdie ersten drei Fälle ist richtig. Für 36 * 36 ist jetzt z.B. so:

36 * 36 
-------
36   36 X 
18   72 X 
 9  144 
 4  288 X 
 2  576 X 
 1 1152 
=======
   1296

Schön :slight_smile:

OK, die Ausgabe für 12345 * 67 ist halt jetzt das:

12345 * 67 
----------
12345   67 
 6172  134 X 
 3086  268 X 
 1543  536 
  771 1072 
  385 2144 
  192 4288 X 
   96 8576 X 
   48 17152 X 
   24 34304 X 
   12 68608 X 
    6 137216 X 
    3 274432 
    1 548864 
==========
    827115

Die erste Zeile ist schön, ohne überflüssige Leerzeichen. Aber … unten stimmt’s dann halt nicht.

Wo soll da was genau woran ausgerichtet sein? (D.h. wo genau sollen dort jetzt weitere Leerzeichen eingefügt werden? Vor oder hinter dem *?)

1 Like

Wenn sich die Gelegenheit ergibt, sag’ deinem Dozenten mal, dass man in der IT Anforderungen explizit machen und vernünftig spezifizieren muss.

Das ist eine sehr gute Idee, ich bin mir sicher, dass viele andere auch durcheinander gekommen sind :smiley:

Das ist zwar Gefrickel, aber die Ausgabe fürdie ersten drei Fälle ist richtig. Für 36 * 36 ist jetzt z.B. so:

Besser hätte man das wahrscheinlich nicht machen können. Ich konnte den Code ohne jegliche Probleme hochladen :slight_smile:

Wo soll da was genau woran ausgerichtet sein? (D.h. wo genau sollen dort jetzt weitere Leerzeichen eingefügt werden? Vor oder hinter dem * ?)

Ich denke, dass es immer noch symmetrisch aussehen sollte, also sowohl vor als auch danach. Jedoch war der Upload schon erfolgreich also brauch ich das nicht mehr :slight_smile: Wahrscheinlich waren nur zwei gleichstellige Zahlen gefragt :smiley:
Ich bedanke mich bei dir herzlich !!!

Oh jeh - das ist so ein Ding, wo man den Code hochlädt und da dann automatische Tests nach „Bestanden“ und „Nicht bestanden“ klassifizieren? Das ist bei „vielen“ Studenten zwar nachvollziehbar (man will nicht 100 Programme einzeln compilieren, starten und die Ausgabe prüfen). Aber … es kann auch sehr unerfreuliche Seiteneffekte haben…

Das funktioniert, wenn 2 Leerzeichen eingefügt werden sollen. Wie ist es bei einem (bzw. einer ungeraden Anzahl)? Ja, es ist nicht mehr relevant, aber… wenn solche Details dann halt in so einem „Online-Checker“ überprüft werden, kann es passieren, dass Studenten Stunden damit verbringen, mit irgendwelchen ifs und printfs die Leerzeichen zurechtzubiegen, was … ja dann nicht mehr sooo viel Lerneffekt hat…

Oh jeh - das ist so ein Ding, wo man den Code hochlädt und da dann automatische Tests nach „Bestanden“ und „Nicht bestanden“ klassifizieren?

Genau so ist es :smiley: Da werden dann verschiedene Parameter übergeben, um sicher zu gehen, dass es richtig funktioniert.

wenn solche Details dann halt in so einem „Online-Checker“ überprüft werden, kann es passieren, dass Studenten Stunden damit verbringen, mit irgendwelchen if s und printf s die Leerzeichen zurechtzubiegen

Die Erfahrung durfte ich nun leider selber sammeln :smiley:

Ich hoffe, das frustriert dann nicht zu sehr. D.h. auch wenn man dann ein Programm dreimal abgeben muss, bis die Leerzeichen stimmen, überwiegt hoffentlich der Teil mit „Hey, ich kann dem Computer sagen, was er machen soll, und der macht dann genau das“.