# Basiswechsel in DrRacket?



## Nummer069 (10. Feb 2020)

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 (10. Feb 2020)

```
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 (10. Feb 2020)

```
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 (10. Feb 2020)

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 (10. Feb 2020)

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.


----------



## mihe7 (10. Feb 2020)

Wobei Ihr Euch den String für die "Ziffern" sparen könnt: 2 <= n < 10


----------



## abc66 (10. Feb 2020)

mihe7 wieder 

(da wollte ich einmal glänzen und fehlerfrei das Alphabet wiedergeben und dann das...)


----------



## Nummer069 (10. Feb 2020)

abc66 hat gesagt.:


> 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 (10. Feb 2020)

abc66 hat gesagt.:


> 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 (10. Feb 2020)

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:

```
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);
  }
}
```


----------



## abc66 (11. Feb 2020)

Naja das wäre noch meine Idee, aber bei den letzten zwei Ausgaben bin ich überfragt, was richtig wäre...:

```
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...


----------



## mihe7 (11. Feb 2020)

```
(define (convert-to-base-n k n)
  (cond [(> k 0) (append (convert-to-base-n (quotient k n) n) (list (modulo k n))) ]
  [else empty]
  )
)
```


----------



## abc66 (11. Feb 2020)

@mihe7 ist das DrRacket?


----------



## mihe7 (11. Feb 2020)

Ja.


----------



## Nummer069 (11. Feb 2020)

mihe7 hat gesagt.:


> ```
> (define (convert-to-base-n k n)
> (cond [(> k 0) (append (convert-to-base-n (quotient k n) n) (list (modulo k n))) ]
> [else empty]
> ...


Vielen, Lieben Dank!!


----------

