Number to bit mask?

Hi,

bin gerade etwas ratlos, das Display hat folgende Bitmaske:

image

Ich suche einen auf Codegröße optimierten Algorithmus, der eine Ziffer/Nummer entgegennimmt und die Bitmaske berechnet, quasi so:

    void printMask(int number) {
        switch (number) {
            case 0:
                System.out.println("0b0000000000111111");
                break;
            case 1:
                System.out.println("0b0000000000000011");
                break;
            case 2:
                System.out.println("0b0000000001011011");
                break;
            // usw.
            default:
                break;
        }
    }

nur ohne switch-case. Hintergrund der Frage ist, das soll auf einem μc laufen, auf dem der Datenspeicher allerdings sehr begrenzt ist…

Hier mal die optimale Lösung für Eingaben von 0 bis 7:

private static int compute(int n)
{
    int a = (n >> 2) & 1;
    int b = (n >> 1) & 1;
    int c = (n >> 0) & 1;
    int na = 1 - a;
    int nb = 1 - b;
    int nc = 1 - c;
    
    int b0 = (na & nc) | (a & c) | b; 
    int b1 = (nb & nc) | (b & c) | na;
    int b2 = nb | c | a;
    int b3 = (a & nb & c) | (na & nc) | (na & b) | (b & nc);
    int b4 = (na & nc) | (b & nc);
    int b5 = (nb & nc) | (a & nb) | (a & nc);
    int b6 = (na & b) | (a & nb) | (b & nc);
    
    return 
        (b0 << 0) |
        (b1 << 1) |
        (b2 << 2) |
        (b3 << 3) |
        (b4 << 4) |
        (b5 << 5) |
        (b6 << 6);
}

Das kannst du ja jetzt verallgemeinern, so dass 8 und 9 auch noch funktionieren :clown_face:

Du kannst einfach ein Polynom 7. Grades berechnen, was dir zu jeder Ziffer den gewünschten Wert ausspuckt.

Für die drei Werte in deinem Beispiel wäre das f(x) = 74x^2 - 134x + 63, was für 0,1,2 die Werte 64, 3 und 91 ergibt.

Zur Berechnung des Polynoms kann man die Gregory-Newton-Formel (hat verschiedene Namen, im Prinzip eine „diskrete Taylor-Entwicklung“) verwenden: Newton's Forward Difference Formula -- from Wolfram MathWorld

Wenn dich die Mathematik dahinter interessiert: Why don't they teach Newton's calculus of 'What comes next?' - YouTube

1 „Gefällt mir“

Ich danke euch. :slight_smile:

Oder es so lassen und nur mit von 0 bis 7 auskommen. :clown_face:

Ich werde das von @Landei erwähnte Polynom 7. Grades weiterverfolgen. :slight_smile:

Hier sind einmal alle Masken:

  1. 0b00111111
  2. 0b00000110
  3. 0b01011011
  4. 0b01001111
  5. 0b01100110
  6. 0b01101101
  7. 0b01111101
  8. 0b00100111
  9. 0b01111111
  10. 0b01101111

Seid ihr sicher, dafür gäbe es eine Funktion, oder werde ich veräppelt? :wink:

Edit: Habe es hinbekommen, zwar nicht rechnerisch/algorithmisch (denn das würde Rahmen dieser Aufgabe sprengen), aber durch „Speichern“ der 10 Zahlen/ints im Programm- bzw. Datenspeicher. Ich dachte anfangs, es gäbe vielleicht ein einfaches Muster, das mir nicht auffiele.

Bei Bedarf kann ich euch den Assemblercode zeigen (sind auch nur 100 Zeilen).

Heißt das, dass du das switch(number) ersetzt hast durch eine return array[number]? Is ja langweilig :confused:

Ich mag die Lösung. Für einen µC der wenige bytes Code nicht in den Speicher bekommt wahrscheinlich schon zu viel Rechenleistung, aber ich mag die Lösung.
Nur eine Frage, ich würde Erwarten dass die Polynom-Formel eben nicht exakt die Punkte trifft, sondern einen Nachkommafehler haben wird. Bei 7,99999999 kommt als Ganzzahl halt 7 heraus. Oder ist das auf Ganzzahlen optimiert?

ja, nur eben in Assembler, falls das wichtig sein sollte.

Bzw. Landeis Lösung (bzw. die von Sir Newton) könnte sehr kompliziert werden, weil der µC nicht multiplizieren kann. Das müsste ich wahrscheinlich aufwändig nachbilden.

Wollt ihr mal sehen?

Man muss schon runden. Für die Koeffizienten …

63,
-1696.3952383547,
3937.3898814929,
-3691.8707345746,
1855.9114585322,
-551.8640625524,
100.0520833418,
-10.8537202389,
0.6465773810,
-0.0162450397

… bekomme ich diese Werte:

0 → 63.0
1 → 5.9999999875992875
2 → 91.00000000939606
3 → 78.99999975658477
4 → 101.99999625316286
5 → 108.99997072449332
6 → 124.99984524591127
7 → 38.999371191253886
8 → 126.9978880607523
9 → 110.99386147316545

Übrigens gibt’s das Kurven-Fitting online: Online calculator for regression calculation. Fit of linear, polynomial, Fourier series, power law, Gauss function and exponential functions.

Aber es ist schon lustig, dass die Araber, die unsere Zahlschrift erfunden haben, keinerlei Systematik bei der Erfindung der Ziffern hatten. :wink: