Basiswechsel in DrRacket?

Nummer069

Mitglied
Hallo und zwar habe ich folgende Aufgabenstellung:
Definieren Sie eine Funktion (convert-to-base-n k n). Diese nimmt eine Zahl k zur Basis 10 entgegen und wandelt diese zur Basis n um. Die Ausgabe erfolgt in einer Liste, deren Elemente die Ziffern der konvertierten Zahl sind. Die Reihenfolge der Ziffern in der Liste ist so, dass die höchste Ziffer zuerst kommt und die Ziffer an der Einerstelle als letztes.
Beispielsweise liefert (convert-to-base-n 27 2) die Liste (list 1 1 0 1 1) zurück.
( Es gilt n,k ∈ N, wobei 2 ≤ n < 10 und 0 ≤ k < 2^16)

Wie man den Basiswechsel von einer Basis in die andere durchführt (zB Zahl immer durch Basis 16 teilen, dann mit dem Rest arbeiten usw.) Aber wie soll sowas "allgemein" für mehrere mögliche Basen programmiert werden? Gibts da irgendeine grundlegende "Formel"/ einen "Algorithmus" dahinter?

Danke für eure Hilfe.
 

abc66

Top Contributor
Java:
	static LinkedList<String> convertIt(int n, int b) {
		LinkedList<String> list = new LinkedList<String>();
		while (n != 0) {
			int m = n % b;
			n = n / b;
			list.add(0, String.valueOf("0123456789abcdefghijklmnopqrstuvwxyz".charAt(m)));
		}
		return list;
	}

	public static void main(String[] args) {
		System.out.println(convertIt(22, 4));
	}
 

httpdigest

Top Contributor
Java:
public static String convertBase10toBaseN(int k, int n) {
  String digits = "0123456789abcdefghijklmnopqrstuvwxyz";
  return java.util.stream.IntStream
        .iterate(k, i -> i / n) // <- repeated division by n
        .takeWhile(i -> i != 0) // <- as long as the number is not 0 (Java 9+!)
        .map(i -> i % n) // <- every digit of the new number is modulo n
        .mapToObj(i -> digits.substring(i, i + 1)) // <- pick correct character
        .reduce("", (s, i) -> i + s); // <- concatenate digits
}
public static void main(String[] args) {
  System.out.println(convertBase10toBaseN(12345, 22));
}

By the way: Was hat "DrRacket" (Racket = LISP-ähnliche Programmiersprache) denn mit Java, geschweige denn mit Java Enterprise Edition zu tun?...
 

abc66

Top Contributor
Bei negativen Zahlen muss man noch aufpassen, aber auch diese können mit ein paar Tricks und Kniffen dargestellt werden.... aber dann muss die Länge bekannt sein.

@httpdigest Schön hergeleitet. Aber es sollte doch eine Liste zurückgegeben werden. :) Was "DrRacket" bedeutet weiß ich auch nicht, ich dachte erst das wäre ein Portal woher die Fragen kommen.
 

httpdigest

Top Contributor
Naja, mich hat schon die Art der Frageformulierung und die dort verwendete Nomenklatur stutzig gemacht:
Definieren Sie eine Funktion (convert-to-base-n k n).
...
Beispielsweise liefert (convert-to-base-n 27 2) die Liste (list 1 1 0 1 1) zurück.
So würde man das als Java-denkender nicht notieren.
Dann hab ich einfach "DrRacket" gegooglet.
 

Nummer069

Mitglied
Bei negativen Zahlen muss man noch aufpassen, aber auch diese können mit ein paar Tricks und Kniffen dargestellt werden.... aber dann muss die Länge bekannt sein.

@httpdigest Schön hergeleitet. Aber es sollte doch eine Liste zurückgegeben werden. :) Was "DrRacket" bedeutet weiß ich auch nicht, ich dachte erst das wäre ein Portal woher die Fragen kommen.
Ich habe die Frage hier im Forum gestellt, weil absolut niemand DrRacket kennt und es somit kein Forum dafür gibt.. Es handelt sich dabei um eine funktionelle Programmiersprache.
 

Nummer069

Mitglied
Bei negativen Zahlen muss man noch aufpassen, aber auch diese können mit ein paar Tricks und Kniffen dargestellt werden.... aber dann muss die Länge bekannt sein.

@httpdigest Schön hergeleitet. Aber es sollte doch eine Liste zurückgegeben werden. :) Was "DrRacket" bedeutet weiß ich auch nicht, ich dachte erst das wäre ein Portal woher die Frage, kommen.
negative Zahlen müssen zum Glück nicht beachtet werden :) trotzdem danke für den Hinweis.
 

httpdigest

Top Contributor
Dann passt meine Stream-Lösung als Ansatz ja schon ganz gut. Du musst dann ja einfach nur noch die List-Primitiven in Racket finden, die denen von Java's Stream entsprechen. Die gibt es in allen funktionalen Programmiersprachen und die verhalten sich überall gleich.
Ein paar konnte ich durch einen kurzen Blick auf Rackets Dokumentation schon identifizeren:
- Java Streams `takeWhile` ist z.B. Rackets takef
- Java Streams `map` ist Rackets map
- Java Streams `reduce` kann mit der ebenfalls in allen funktionalen Programmiersprachen sehr bekannten foldl (links-assoziatives Fold) implementiert werden
Wenn du dich also in funktionaler Programmierung auskennst, dann findest du dich sehr schnell in Racket rein.

EDIT: Wenn das Ergebnis (wie @abc66 schon sagt) wieder eine Liste/Stream sein soll:
Java:
import static java.util.stream.IntStream.iterate;
import static java.util.stream.Stream.*;
import java.util.function.BinaryOperator;
import java.util.stream.Stream;
public class Basiswechsel {
  public static Stream<Character> convertBase10toBaseN(int k, int n) {
    String digits = "0123456789abcdefghijklmnopqrstuvwxyz";
    BinaryOperator<Stream<Character>> unused = (a, b) -> null;
    return iterate(k, i -> i / n) // <- repeated division by n
          .takeWhile(i -> i > 0) // <- as long as the number is greater than 0 (Java 9+!)
          .map(i -> i % n) // <- every digit of the new number is modulo n
          .mapToObj(digits::charAt) // <- pick correct character
          .reduce(empty(), (s, i) -> concat(of(i), s), unused); // <- reduce to reversed stream
  }
  public static void main(String[] args) {
    convertBase10toBaseN(12345, 10).forEach(System.out::print);
  }
}
 
Zuletzt bearbeitet:

abc66

Top Contributor
Naja das wäre noch meine Idee, aber bei den letzten zwei Ausgaben bin ich überfragt, was richtig wäre...:
Java:
	static String convertIt(int n, int b) {
		boolean neg = false;
		if (n < 0) {
			n = Integer.MAX_VALUE + n + 1;
			neg = true;
		}
		String list = "";
		while (n != 0) {
			int m = n % b;
			n = n / b;
			list = String.valueOf("0123456789abcdefghijklmnopqrstuvwxyz".charAt(m)) + list;
		}
		if (neg) {
			while (list.length() < 31) {
				list = "0" + list;
			}
			list = "1" + list;
		}
		return list;
	}

	public static void main(String[] args) {
		System.out.println(convertIt(-42, 2));
		System.out.println(Integer.toBinaryString(-42));
		System.out.println(convertIt(Integer.MAX_VALUE / 3, 3));
		System.out.println(Integer.toString(Integer.MAX_VALUE / 3, 3));
		System.out.println(convertIt(-Integer.MAX_VALUE / 3, 3));         // ?
		System.out.println(Integer.toString(-Integer.MAX_VALUE / 3, 3));  // ?
	}

Man wandelt negative Zahlen halt so selten zur Basis 3 um...
 

Neue Themen


Oben