Java Nach float-Division die letzten noch wichtigen Nachkommastellen bestimmen und bis dorthin kürzen ...

CyborgBeta

Commander
Registriert
Jan. 2021
Beiträge
2.854
Guten Nabend,

ich hab so was:

Java:
import java.util.TreeMap;

public class Main {
    public static void main(final String[] args) {
        TreeMap<String, Integer> shortened = new TreeMap<>();
        for (int i = 0; i <= 300; i++) {
            float a = i / 150f;
            String withoutFirstDigits = String.valueOf(a).substring(3);
            shortened.compute(withoutFirstDigits, (k, v) -> v == null ? 1 : v + 1);
        }
        shortened.entrySet().forEach(System.out::println);
    }
}

Ausgabe:

Code:
=21
066666=4
0666665=1
0666666=2
06666667=1
0666667=3
066667=9
133333=8
1333333=3
13333334=1
1333334=3
1333336=1
133334=4
2=20
266666=4
2666664=1
2666665=2
26666667=1
2666667=3
2666668=1
266667=8
333333=10
3333333=1
33333335=1
3333334=4
3333335=1
3333336=1
333334=2
4=20
466666=4
4666665=1
4666666=4
46666667=1
4666667=2
466667=8
533333=8
5333332=1
5333333=2
53333335=1
5333334=2
5333335=2
533334=4
6=20
666666=2
6666664=1
6666665=1
6666666=1
6666667=4
6666668=1
666667=10
733333=8
7333333=5
7333334=1
7333335=1
7333336=1
733334=4
8=20
866666=4
8666664=1
8666666=3
86666666=1
8666667=2
8666668=1
866667=8
933333=9
9333332=1
9333333=1
93333334=1
9333334=2
9333335=2
933334=4

Und hier sieht man auch gleich das Problem:

133333=8
1333333=3
13333334=1
1333334=3
1333336=1
133334=4

1333333, 13333334 und 1333334 sollen gerundet/zusammengefasst werden in 133333, und 1333336 soll zu 133334 werden.

Wie kann man solche "Cluster" bilden, also die "vereinzelten" Werte dem nächstgelegenen, größeren Nachbarn zuordnen?

Es soll also weniger "Ausreißer" geben, wodurch alle Zahlen dann einfacher zu lesen wären - aber gleichzeitig soll jede Zahl natürlich auch eindeutig bleiben.

Danke
 
Wie wäre es denn damit, dass du irgendwo definierst, welche Grenzen es gibt, und dann mit größer/kleiner vergleichst, also prüfst, in welchem Intervall eine Zahl ist?

Also die Definition der Intervalle geht selbstverständlich auch programmatisch.
 
  • Gefällt mir
Reaktionen: BeBur und CyborgBeta
CyborgBeta schrieb:
Es soll also weniger "Ausreißer" geben, wodurch alle Zahlen dann einfacher zu lesen wären - aber gleichzeitig soll jede Zahl natürlich auch eindeutig bleiben.
Was bedeutet für dich eigentlich "eindeutig"?

Und für mich klingt das irgendwie wie ein XY-Problem. Vermutlich aber, weil das Beispiel sehr wahrscheinlich nicht repräsentativ genug für die tatsächliche Nutzung ist.

Vielleicht wäre auch der Datentyp BigDecimal sinnvoller, aber das kann man pauschal nicht sagen.
 
  • Gefällt mir
Reaktionen: kuddlmuddl, BeBur und CyborgBeta
tollertyp schrieb:
Wie wäre es denn damit, dass du irgendwo definierst, welche Grenzen es gibt, und dann mit größer/kleiner vergleichst, also prüfst, in welchem Intervall eine Zahl ist?
Ja, dann wäre die Frage, woher ich weiß, wie ich die Grenzen festlegen muss?
Ergänzung ()

0x8100 schrieb:
ich bin ja nicht mit java unterwegs aber suchst du nicht setMaximumFractionDigits? bzw. runden auf eine bestimmte anzahl an nachkommenstellen?
Die Anzahl der Nachkommastellen festlegen, das wäre erst der zweite Schritt. Vorher muss ich ja wissen, wie viele Stellen.
Ergänzung ()

Und die Anzahl wäre auch nicht immer die gleiche ...
 
Ich hab's jetzt mehrmals versucht zu verstehen. Aber wie soll
CyborgBeta schrieb:
aber gleichzeitig soll jede Zahl natürlich auch eindeutig bleiben.
je funktionieren? Du rundest ja, damit verlierst du ja Genauigkeit und damit die Eindeutigkeit.

1333333, 13333334 sollen zusammengefasst werden in deinem Beispiel. Danach weißt du aber nicht mehr ob 13333334 nicht eigentlich 1333333(1|2|3|4) gewesen wäre.
 
  • Gefällt mir
Reaktionen: drrrk
CyborgBeta schrieb:
Ja, dann wäre die Frage, woher ich weiß, wie ich die Grenzen festlegen muss?
Das ist eine Frage, die DU beantworten musst. Wir wissen doch gar nicht, was du vor hast und was diese Clusterung überhaupt für einen Zweck hat.
 
  • Gefällt mir
Reaktionen: tollertyp und BeBur
Tornhoof schrieb:
Aber wie soll
je funktionieren? Du rundest ja, damit verlierst du ja Genauigkeit und damit die Eindeutigkeit.
Es stehen ja noch drei Stellen vorne (inkl. Dezimalzeichen), die habe ich mit substring vorwegabgeschnitten, um das Problem deutlicher zu machen.
Ergänzung ()

Krik schrieb:
überhaupt für einen Zweck hat.
Vereinfacht gesagt, um redundante Nachkommastellen zu entfernen.
 
CyborgBeta schrieb:
133333=8
1333333=3
13333334=1
1333334=3
1333336=1
133334=4

1333333, 13333334 und 1333334 sollen gerundet/zusammengefasst werden in 133333, und 1333336 soll zu 133334 werden.
Sollen die Gleichheitszeichen eine Funktionszuweisung ausdrücken?

Die Anzahl an Stellen ist sehr unübersichtlich, nimm doch u+202f zur Gruppierung.

Jedenfalls, passt eine etwaige Funktionszuweisung ja nicht mehr, wenn
1,333 333 = 1,333 333 4 = 1,333 334. Soll der (von mir angenommene) Funktionswert dann 1 sein oder 3 oder sonst was?

Ich würde somit ebenfalls sagen, dass hier noch Erklärungsbedarf herrscht, was überhaupt gemacht werden soll.
 
  • Gefällt mir
Reaktionen: DEADBEEF
CyborgBeta schrieb:
Vereinfacht gesagt, um redundante Nachkommastellen zu entfernen.
CyborgBeta schrieb:
Die Anzahl der Nachkommastellen festlegen, das wäre erst der zweite Schritt. Vorher muss ich ja wissen, wie viele Stellen.
vielleicht habe ich ja immer noch nicht verstanden, was du eigentlich vorhast, aber in python kann man mit format strings einfach sagen, wieviele nachkommastellen man haben will (dabei wird auch gleich gerundet) und ob diese aufgefüllt werden sollen, damit man immer die gleiche länge hat:

Code:
number=123.456789

print(f'{number:.3f}')
123.457

print(f'{number:.5f}')
123.45679

print(f'{number:.9f}')
123.456789000

google sagt, dass java auch format strings hat und das sieht ziemlich ähnlich aus. vielleicht hilft das?
 
Ich würde mit 2er-Tupeln arbeiten, die a) eine Gruppierung und b) den ursprünglichen Wert (inkl. aller Nachkommastellen) enthalten.

Und dann durch eine bis zwei Schleifen würde ich zuerst alle Werte in die Tupel legen und im nächsten Schritt aus den Werten die Gruppierung ermitteln.
 
simpsonsfan schrieb:
Sollen die Gleichheitszeichen eine Funktionszuweisung ausdrücken?
Nein, hinter dem Gleichheitszeichen steht einfach nur die Anzahl der Vorkommen.
 
Danke. Ja, ich glaube, danach suche ich...

Gesucht ist eine optimale Spaltenbreite, also wie "wenige" Nachkommastellen jeweils benötigt werden, um alle Zahlen des Bildbereichs darstellen zu können...
 
Glaube, so ist es richtig:

Java:
import java.util.HashSet;
import java.util.TreeMap;
import java.util.TreeSet;

public class Main {
    public static void main(final String[] args) {
        int a = 0;
        int b = 300;
        float c = 150f;
        int min = getMinFractionDigits(a, b, c);
        System.out.println("min = " + min);
        TreeSet<String> treeSet = new TreeSet<>();
        for (int i = a; i <= b; i++) {
            String s = String.format("%." + min + "f", i / c);
            if (treeSet.contains(s)) {
                throw new IllegalArgumentException(s);
            }
            treeSet.add(s);
        }
        treeSet.forEach(System.out::println);
    }

    public static int getMinFractionDigits(int a, int b, float c) {
        int d = 0;
        a:
        while (true) {
            HashSet<String> set = new HashSet<>();
            for (int i = a; i <= b; i++) {
                String s = String.format("%." + d + "f", i / c);
                if (set.contains(s)) {
                    d++;
                    continue a;
                }
                set.add(s);
            }
            return d;
        }
    }
}

Jetzt suche ich für getMinFractionDigits eben nur noch eine Formel... (denn es könnte ja sein, dass diese Methode öfters aufgerufen werden muss...)
 
Ich glaube, ich habe die Problemstellung durchschaut: er hat ein Set mit n Zahlen und möchte die niedrigste Anzahl von Nachkommastellen ermitteln, mit der er nach dem Runden immer noch n unterschiedliche Zahlen hat, und nicht etwa weniger, weil welche durch die Rundung gleich werden.
 
  • Gefällt mir
Reaktionen: CyborgBeta
@H4110 Danke für die kurze Erklärung!

Auf die persönlichen Anfeindungen werde ich nicht weiter eingehen.

Dijkstra hat mal einen Aufsatz über Goto geschrieben, in Ausnahmefällen darf und kann man es jedoch verwenden...

Das mit dem Infiniti Regress wäre natürlich ein Problem, aber deshalb suche ich auch nach einer Formel.
Ergänzung ()

SuperCube schrieb:
Ich entwickle Software seit über 20 Jahren.
Das spielt keine Rolle, es trägt nicht zum Thema bei. Sogar, wenn du der Kaiser von China wärst, würde mich das nicht beeindrucken (oder provozieren). Meist kommen solche Aussagen auch von Studienabbrechern, oder solchen, die es mit viel Glück doch geschafft haben ...

@ Moderation : Ggf. könnte dieses Thema geschlossen werden? Danke.
 
Zuletzt bearbeitet:
Kann mir nicht vorstellen, dass es dafür eine Formel gibt, aber es geht effizienter: bei einem SortedSet reicht es, wenn ich mich nicht irre, das aktuelle und nächste Element zu betrachten. Vor dem Loop Anzahl der Nachkommastellen d mit niedrigem Wert initialisieren. Solange aktuelles und nächstes Element gerundet gleich sind, d erhöhen.

Eine Implementierung als Collector fände ich elegant. Der muss dann aber auch mit gleichen Elementen klar kommen und checken, dass der Stream sortiert ist.
 
  • Gefällt mir
Reaktionen: CyborgBeta
CyborgBeta schrieb:
Vereinfacht gesagt, um redundante Nachkommastellen zu entfernen.
Vielleicht nicht Dinge immer vereinfacht, sondern exakt sagen.

Weil was hat das mit redundanten Nachkommastellen zu tun?
1333333, 13333334 und 1333334 sollen gerundet/zusammengefasst werden in 133333, und 1333336 soll zu 133334 werden.

Und das "warum" hast du ja nach wie vor nicht erklärt, das "warum" Ist aber für mich als Software-Entwickler immer das wichtigste. Weil das "warum" hilft meistens das "was" zu verstehen.
 
  • Gefällt mir
Reaktionen: CyborgBeta
Hmm, also, der Code in #15 macht, was ich in #17 beschrieben habe. Das ist was anderes, als Cluster zusammenzufassen, wie im OP beschrieben.

CyborgBeta schrieb:
1333333, 13333334 und 1333334 sollen gerundet/zusammengefasst werden in 133333, und 1333336 soll zu 133334 werden.

CyborgBeta schrieb:
aber gleichzeitig soll jede Zahl natürlich auch eindeutig bleiben.
Das widerspricht sich. Mit dem Code in #15 erreichst Du letzteres bei minimaler Anzahl von Nachkommastellen, aber nicht ersteres.
 
  • Gefällt mir
Reaktionen: CyborgBeta

Ähnliche Themen

Zurück
Oben