Implementierung Horner-Schema in WHILE-Schleife zur Umrechnung von INT nach HEX

Guten Tag zusammen. Ich beschäftige mich derzeit mit WHILE-Schleifen und dem Horner-Schema. Dabei komme ich irgendwie nicht wirklich weiter, da mir ein Ansatz für die Implementierung fehlt.

Folgende Ausgangssituation:
Ich lese eine Unicode-Zeichendarstellung per Schleife und Array ein. Form: \uxxxx

Die ersten beiden Eingaben ‘’ und ‘u’ werden über IF-Abfragen geprüft. Die folgenden vier Zeichen speichere ich zur späteren Wiederverwendung in einem CHAR-Array mit der Länge 4. Schlussendlich überprüfe ich noch an der 7. Stelle ob da ein ’
’ oder ‘\r’ “steht”, ansonsten wird die Eingabe als zu lang angesehen.

Am Ende muss ich nun die im Array gespeicherten Zahlen über das Horner-Schema von INT nach HEX umwandeln, damit ich dann das richtige Unicode-Zeichen ausgeben lassen kann. Dabei sieht das Konstukt auf dem Papier wie folgt aus:
(1. Stelle * (161616)) + (2. Stelle * (16*16)) + (3. Stelle * (16)) + (4. Stelle * (1))

Mein Code sieht derzeit so aus: Pastebin : JavaCode

Die Implementierung muss ungefähr ab Zeile 56 erfolgen. Leider habe ich hier keine Ahnung wie genau das aussehen soll.

Ich wäre sehr dankbar, wenn mir jemand weiterhelfen könnte.

*** Edit ***

Eigentlich liegt mein Problem nicht am Verständnis der Aufgabe. Ich weiß, dass ich in einem Array mit der Index-Übergabe auf eine bestimmte Stelle zugreifen kann. D. h. bei einem char[] test = new char[4] würde der Index von 0 - 3 entstehen. Also könnte ich mit char[0], char[1], char[2], char[3] auf die Zellen zugreifen.

Das einzige was mir fehlt um die Aufgabe zu beenden ist das Verständnis dafür, wie ich die in das Array an Index-Platz [0] eingelesene Zahl um den Faktor 16 hoch 3 erhöhen kann. Dann müsste ich am Ende nur noch die neu definierten Index-Plätze zusammenzählen und hätte meine HEX-Zahl. Zumindest soweit die Theorie.

Hab’ nur schnell drübergeguckt, aber … vielleicht hängt’s daran, dass du den Array rückwärts durchlaufen müßtest. Irgendwo könnte GROB sowas vorkommen wie

int stelle = array.length - 1;
int aktuellerFaktor = 1;
while (stelle >= 0)
{
    // That's where the magic happens 
    ...

    // Für die nächste Stelle:
    aktuellerFaktor *= 16; 
    stelle--;
}

So geht’s:

 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javaapplication1;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @author CB
 */
public class ZeichenInHex {

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.print("Zeichen (mit \"\\uXxXx\"): ");
        String line = br.readLine();
        if (!line.matches("^\\\\u[0-9a-f]{4,4}$")) {
            return;
        }
        String hex = line.substring(2);
        int val =
                (hex.charAt(0) <= '9' ? hex.charAt(0) - '0' : hex.charAt(0) - 'a' + 10) * 16 * 16 * 16
                + (hex.charAt(1) <= '9' ? hex.charAt(1) - '0' : hex.charAt(1) - 'a' + 10) * 16 * 16
                + (hex.charAt(2) <= '9' ? hex.charAt(2) - '0' : hex.charAt(2) - 'a' + 10) * 16
                + (hex.charAt(3) <= '9' ? hex.charAt(3) - '0' : hex.charAt(3) - 'a' + 10) * 1;
        System.out.println("lin = " + line);
        System.out.println("hex = " + hex);
        System.out.println("val = " + val);
        System.out.println("chr = " + (char) val);
    }
}```


run:
Zeichen (mit “\uXxXx”): \u007e
lin = \u007e
hex = 007e
val = 126
chr = ~
BUILD SUCCESSFUL (total time: 6 seconds)



Mit 'ner Schleife ist das immer so ein Doppel Gemoppel:

```int value = 0;
for (int i = lin.length() - 1; i >= 0; i--) {
    // tue was mit i und so...
}```

Darum ging’s ja nicht :rolleyes: Vielleicht mal lesen: http://de.wikipedia.org/wiki/Horner-Schema

Ja, ist doch voll langweilig und innerhalb des Ausdrucks auf der rechten Seite der meiner Zuweisung schon realisiert.

16 * … * 16 * 1 kann der Compiler optimieren; +, - geht relativ fix.

Alternativ auch mal: string.toLowerCase() und Integer.parseInt(hex, 16) anschauen.

Edit: Er kann das ja in Methoden/statischen Funktionen modularisieren und dann seine Hausaufgaben abgeben - oder er kopiert’s einfach und ändert ein paar Variablenbezeichnungen. Dagegen hab ich überhaupt nichts. Als ich das noch machen musste, hatte ich immer 'ne 1.

Und gelernt hat er damn nichts weil er es nicht selber gwmacht hat. Der TO hat ja gefragt wie man das mit den Arrays macht und nicjt mach der Komplettloesung…

gäähn - Kaffee in der Hand, das war eine lange Nacht

Erstmal danke ich euch für eure Antworten.
@CyborgBeta : Bei deinem Code versteh ich nur Bahnhof. Deswegen bringt er leider gar nichts. Trotzdem Danke für deine Mühe. ^^

ABER: Nach nun rund 12 Stunden des eifrigen Rumprobierens und kaum Schlaf kam mir heute Morgen die ultimative Erleuchtung in diesem Problem. Und ich bin überaus stolz auf mich. :smiley:

Ich habe die Grundidee mit der Schleife komplett verworfen und einfach mit den Arrays und dessen Werten an bestimmten Index-Punkten herumgespielt. So war es um einiges einfacher das Horner-Schema am Ende zu implementieren. Beginnt ab Zeile 53. Damit nicht jeder verzweifelt suchen muss, falls er mal das gleiche Problem hat, hier noch meine Lösung:

       
        public static void main(String[] args) throws Exception {
               
                System.out.println("Zahl in Form: \\uxxxx eingeben");
               
                char erstesZeichen = (char)System.in.read();
               
                if ( erstesZeichen != '\\') {
                       
                        System.out.println("Erstes Zeichen \\");
                        return;
                       
                }
               
                char zweitesZeichen = (char)System.in.read();
               
                if ( zweitesZeichen != 'u') {
                       
                        System.out.println("Zweites Zeichen u");
                        return;
                       
                }
               
                char[] vierStellen = new char[4];
                int stellen = 0;
               
                while (stellen < vierStellen.length) {
                       
                        vierStellen[stellen] = (char)System.in.read();
                       
                        if (!(vierStellen[stellen] >= '0' && vierStellen[stellen] <= '9')
                        && !(vierStellen[stellen] >= 'a' && vierStellen[stellen] <= 'f')) {
                               
                                System.out.println("Wert zwischen 0-9 und a-f");
                                return;
                               
                        }
                       
                        stellen++;
                       
                }
               
                char ueberlauf = (char)System.in.read();
               
                if (!(ueberlauf == '
' || ueberlauf == '\r')) {
                       
                        System.out.println("Bitte denken Sie an maximale Zeichenzahl von 6.");
                        return;
                       
                }
                
                int d1 = 0;
                int d2 = 0;
                int d3 = 0;
                int d4 = 0;
                
                if (vierStellen[0] >= '0' && vierStellen[0] <= '9') d1 = (int) vierStellen[0] - '0';
                if (vierStellen[1] >= '0' && vierStellen[1] <= '9') d2 = (int) vierStellen[1] - '0';
                if (vierStellen[2] >= '0' && vierStellen[2] <= '9') d3 = (int) vierStellen[2] - '0';        
                if (vierStellen[3] >= '0' && vierStellen[3] <= '9') d4 = (int) vierStellen[3] - '0';
         
                if (vierStellen[0] >= 'a' && vierStellen[0] <= 'f') d1 = vierStellen[0] - 'a' + 10;
                if (vierStellen[1] >= 'a' && vierStellen[1] <= 'f') d2 = vierStellen[1] - 'a' + 10;
                if (vierStellen[2] >= 'a' && vierStellen[2] <= 'f') d3 = vierStellen[2] - 'a' + 10;
                if (vierStellen[3] >= 'a' && vierStellen[3] <= 'f') d4 = vierStellen[3] - 'a' + 10;
                
                int dez= (d4 * 1) + (d3 * 16) + (d2 * (16 * 16)) + (d1 * (16 * 16 * 16));
                
                System.out.println("hex:" + vierStellen[0] + vierStellen[1] + vierStellen[2] + vierStellen[3]);
                System.out.println("zeichen: " +  (char) dez);
                System.out.println("dez:" + dez);
               
        }
       
}```

Falls jetzt noch jemand eine elegantere Lösung mit Hilfe einer Schleife wissen würde, kann er mir das gerne noch mitteilen. Immerhin glaube ich gern, dass es da noch einen wesentlich eleganteren Weg gibt.

Mal davon abgesehen, dass die “Java”-Lösung des zu Grunde liegenden Problems mit [JAPI]Pattern[/JAPI] Integer.parseInt(hexString,16);in 3 Zeilen zu lösen wäre und das eigentlich keine Aufgabenstellung ist, die man in eriner OO-Sprache nachprogrammieren sollte haben die Andere die Lösung ja schon skizziert:
Die in dezimal umgerechenten Stellen d1 - d4 sollten ebenfalls in einem Array (brrr…) abgelegt werden. Dann kann man die Multiplikation der Stellen mit ihrem Sellenwert (d[SUB]x[/SUB]16(x-1)) und die Summierung in der Variablen dez auch in einer Schleife abfrühstücken. Der Schlüssel ist: die Stellenwerte sind umgekehrt zu der Reihenfolge in der wir sie lesen!:idea:

bye
TT

Hat jemand den Wiki-Artikel gelesen? Ja, ich auch nicht, aber … hat ihn jemand überflogen? Beim Horner-Schema geht es eigentlich um Polynome. Wenn man mit dem Horner-Schema ein Polynom vom Grad n behandeln will, schreibt man eben nicht 1616…(n-mal)…*16, sondern … verwendet das Horner-Schema. Damit kann man dann auch relativ leicht Ableitungen berechnen und so. Es geht hier ja nicht darum, eine Aufgabe zu lösen, die mit einem Integer.parseInt(…,16) schon erledigt wäre, sondern um die Idee, die dahinter steckt. Aber was liegt mir dran :rolleyes:

Das Horner-Schema soll in diesem Fall nur als „Denkstütze“ dienen und nicht 1:1 hergenommen werden. Und das Horner-Schema beschäftigt sich in dem Fall eben damit, dass aus allen Exponenten die Herleitung durch die Ausmultiplikation und Addition erfolgt.

Um die einzelnen abgefragten Stellen umzurechnen würde sich beispielsweise ein 16² ergeben. Mit dem Horner-Schema soll das dann allerdings als 1616 dargestellt werden. Und die vierte Stelle wäre dann mal Faktor 16³ (Exponent also 3), deswegen ergibt sich: 1616*16. Danach sollen alle Werte zusammenaddiert werden und ergeben das notwendige Ergebnis.

Wenn das nicht so wäre, hab ich scheinbar den Grundgedanken des Horner-Schema komplett missverstanden. :smiley:

Im OP hast du geschrieben

über das Horner-Schema von INT nach HEX umwandeln

In deiner Lösung wandelst du jetzt von Hex nach Int ohne Horner-Schema um. Was nun?

PS: Der Sinn des Horner Schemas ist Multiplikationen durch Additionen zu ersetzen, weil Addieren einfacher und schneller geht.

Sehe ich auch so. Darauf zielt die Aufgabenstellung wohl ab.

Ein Vorteil, der mir noch in Erinnerung ist: man braucht keine Potenzierung.

Die Darstellung einer Hexadezimalen Zahl passt perfekt ins Horner-Schema. Eigentlich passt jede Zahl zu einer beliebigen Basis perfekt ins Schema.

Davon würde ich jetzt einfach mal ausgehen. Die Exponenten fallen beim Horner-Schema nämlich weg. Die Klammerung ist das Geheimnis.

Die Definition auf Wikipedia (Horner-Schema – Wikipedia) reicht eigentlich schon aus, um das umzusetzen. Gesetzt den Fall, man weiß, wie man eine Zahl in ein Polynom umwandelt.
Kleiner Tip: x = 16.

@Spectznaz : Ich kenne die Aufgabenstellung ja nicht. Sollt ihr euch streng an das Horner-Schema halten (weiß ich nicht, was das ist), dann ist mein Ansatz/Lösung oben falsch.

Aber ich wiederhole: es geht um 4 Hexadezimalzeichen/ziffern. Also 161616 (± ist wie erwähnt belanglos), was der Compiler einfach durch eine Konstante ersetzen kann. ‘a’ + 10 kann auch noch ersetzt werden, denn (a±b)±c==a±(b±c).

Einzig langsam wird sein: !line.matches("^\\u[0-9a-f]{4,4}$") bzw. !line.matches("^\\u[\da-f]{4,4}$") und line.substring(2).

(Du sollst wissen, wie man in einer Schleife auf 0-9ora-forA-F prüfen kann.)

Strings sind quasi nichts anderes als immutable/unveränderliche char-Arrays. Der Zugriff mit hex.charAt(x) geht fix. Erklär’ uns doch mal kurz, wie ihr das unter Zuhilfenahme von Arrays berechnen sollt.

Edit: ZeichenInHex und “Zeichen (mit” sind vielleicht nicht optimale Namen - ich habe immer k. P., wie cih sie nennen soll.

[quote=Spectznaz]Wenn das nicht so wäre, hab ich scheinbar den Grundgedanken des Horner-Schema komplett missverstanden.[/quote]Ich glaube, dass hast Du.

Das Hornerer-Schema will gerade nicht (wie vom TO gemacht) dass man die jeweilige Potenz von x(hier 16) explizit bildet, sondern dass diese sich implizit bildet. Ich rechne das mal vor:```Ausgangszahl: 0x01AF
var ergebnis :=0 // Vorbelegung vor dem ersten Durchlauf
//Schleifenbegin:
var stelle := 0 // erste Stelle (nach 0x…)
ergebnis := ergebnis16 // 16 ist der Wert von x ergebnis ist 0
ergebnis := ergebnis + stelle // ergebnis ist 0 = (0
16^0)
Weitere Stelle zu bearbeiten??-> ja, nächster schleifendurchlauf:
stelle := 1 // zweite Stelle
ergebnis := ergebnis16 // ergebnis ist 0 (016^1)
ergebnis := ergebnis + stelle // ergebnis ist 1 = (016^1 + 116^0)
Weitere Stelle zu bearbeiten??-> ja, nächster schleifendurchlauf:
stelle := 0xA = 10 // zweite Stelle
ergebnis := ergebnis16 // ergebnis ist 16 (016^2 + 116^1)
ergebnis := ergebnis + stelle // ergebnis ist 26 = (0
16^2 + 116^1 + 1016^0)
Weitere Stelle zu bearbeiten??-> ja, nächster schleifendurchlauf:
stelle := 0xf = 15 // zweite Stelle
ergebnis := ergebnis16 // ergebnis ist 416 = (016^3 + 116^2 + 1016^1)
ergebnis := ergebnis + stelle // ergebnis ist 431 = (016^3 + 116^2 + 1016^1 + 1516^0)
Weitere Stelle zu bearbeiten??-> nein.

0x01AF = 431```

bye
TT

Musst du immer Groß- und Kleinschreibung mischen? := sagt mir nichts, ich kenne das nur als „ist definiert durch“. Wenn ich das richtig sehe:
a16^3+b16^2+c*16+d=16(16(16(a)+b)+c)+d
Die Anzahl der Multiplikationen (arithmetisch) möchte ich jetzt mal nicht zählen und vergleichen…
Ok, ich mach’s: 6x die Multiplikation (arithmetisch), mindestens 4 Zwischenergebnisse, 3x die Addition; und oben sind es 3x Multiplikation, 4x „-“-Addition. 2 Zwischenergebnisse. Das spricht glaube ich Bände.
Natürlich will ich mich nicht ständig selbst loben, deshalb: Eure Lösungen sind alle viel, viel besser und viel, viel schöner als meine. Ich verneige mich vor Euch und versuche mich unauffällig zu entfernen. :kiss: Schmatzi Bussi

[quote=CyborgBeta]Eure Lösungen sind alle viel, viel besser und viel, viel schöner als meine.[/quote]Mein “Code” ist keine Lösung (es kompiliert ja nocht mal…).

Es ist die Prosaform von dem, was eine Schleife tun sollte, wenn sie das Hornerer-Schema implementiert. Ich wollte zeigen, wie sich das Ergebnis in der Variablen ergebnis entwickelt, ohne dass explizit potenziert wird. Scheint mir nicht gelungen zu sein… :o(

bye
TT

Diese Arroganz kannst du dir sparen. Deine „Lösung“ ist keine Lösung für die Aufgabenstellung. Ich hebe vom Threadtitel mal die Punkte hervor, die dein Lösungsvorschlag nicht umsetzt:
„Implementierung Horner-Schema in WHILE-Schleife zur Umrechnung von INT nach HEX“

Wenn sich die Anforderung ändert und plötzlich eine 10-stellige Zahl eingelesen werden soll, hast du dann vor, per C&P deine Codezeile zu kopieren, den Index jeweils anzupassen und hinten ein *16 hinzuzufügen? Da kannst du das Programmieren gleich sein lassen…

Überheblichkeit scheint für DICH auch kein Fremdwort zu sein, @cmrudolph . Ich hab’ persönlich noch nicht so viele Unicode-Zeichen, die größer als 65535 wären, gesehen - das verlangte die Aufgabenstellung übrigens auch nicht.

Ich leg’ gerne noch 'ne Schüppe drauf: Meine Lösung ist die (bisher) beste und es gibt in JAVA auch keine schnellere Umsetzung. Nach einer kompetenten Antwort, außer einem Verweis auf Wikipedia und so etwas wie “Gesetzt den Fall [unter der Voraussetzung(, dass …), wenn die Annahme zutrifft(, dass …)], dass man voll die Ahnung hat…”, sucht man nach einer kompetenten Antwort von DIR in diesem Thread allerdings vergeblich.

DU kannst jetzt selbstverständlich gerne in DEINER Glaskugel nachschauen, wie wohl die Aufgabenstellung war. Interessiert mich aber nicht.

PS. Einen Vergleich DEINE “Skills” vs. meine möchte ich jetzt gar nicht anfangen - gerade keine Lust, irgendjemanden vorzuführen.

Hui, da hat ja jemand dicke Eier :smiley: Eigentlich bin ich bei „dieser Art von Unterhaltung“ ja eher zurückhaltend, aber ausnahmsweise, ganz kurz:

  • Übergeordnet in bezug auf die Zielsetzung: Es wird weder eine while-Schleife noch das Horner-Schema verwendet (ja, zugegeben, vielleicht schließe ich zu sehr von mir auf andere, wenn ich davon ausgehe, dass jemand der eine Frage stellt, die Antwort auf die Frage haben will)
  • In bezug auf die Art der Lösung, konzeptuell: Sie ist schlecht erweiterbar, z.B. für mehr Stellen, oder wenn man auch Großbuchstaben erlauben will.
  • In bezug auf den Stil: Alles mit 4 ternären Operatoren in eine Zeile zu schreiben - neee…
  • Auch wenn der JIT einen da retten wird: Allgemein dürfte 12 mal „hex.charAt“ (für 4 Zeichen) der Performance nicht zuträglich sein
    Vermutlich ist sie sogar schneller als Integer.parseInt, aber nicht, wenn man das Matchen der RegEx (als Fehlerüberprüfung) mit einrechnet.
    Und nun würde ich dir raten, meine Kompetenz in Frage zu stellen, sonst denken alle, du hättest verloren.

hex.charAt benötigt gar nix, außer vielleicht eine Addition. Es gibt kein Unicode-Zeichen, dessen Wert größer 0xffff wäre (noch mal)… Warum sollte ich eine Aufgabe falsch bearbeitet haben, wenn die Aufgabestellung nicht bekannt ist, das Ergebnis jedoch richtig ist? Könnt Ihr mir mal erklären, warum ich dafür angemault werde? Verlangt war ein Esel, bekommen hat er einen Esel, dann müsst Ihr nicht nach Kamel schreien. Eine beliebig lange Hexadezimalzahl passt weder in ein int noch in ein long.

Trotzdem beantworte ich gerne auch unsinnige Fragen:

 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javaapplication1;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;

/**
 * @author CB
 */
public class HexNachDezi {

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.print("Zeichen (in Form \"\\uXxXx....\"): ");
        String line = br.readLine();
        if (!line.matches("^\\\\u[0-9a-fA-F]{4,}$")) {
            return;
        }
        String hex = line.substring(2);
        BigInteger dez = BigInteger.ZERO;
        for (int i = 0; i < hex.length(); i++) {
            char c = hex.charAt(i);
            if (c >= '0' && c <= '9') {
                dez = dez.add(BigInteger.valueOf(c - '0'));
            } else if (c >= 'A' && c <= 'F') {
                dez = dez.add(BigInteger.valueOf(c - ('A' - 10) ));
            } else if (c >= 'a' && c <= 'f') {
                dez = dez.add(BigInteger.valueOf(c - ('a' - 10) ));
            } else {
                throw new IllegalArgumentException(
                        "Sie sind leider zu bloed, [0-9a-fA-F]+ einzugeben.");
            }
            if (i != hex.length() - 1) {
                dez = dez.multiply(BigInteger.valueOf(16));
            }
        }
        System.out.println("lin = " + line);
        System.out.println("hex = " + hex);
        System.out.println("dez = " + dez);
        if (dez.compareTo(BigInteger.valueOf(Long.parseLong("ffff", 16))) > 0) {
            System.out.println("Ihre Eingabe ist leider kein Unicode-Zeichen.");
        } else {
            System.out.println("chr = " + (char) dez.longValue());
        }
    }
}```