Das „Schema“ aus dem ersten Post ist nur eine Sammlung von Beispielen. Wie es bei Computern und Programmierung so üblich ist, müßte man genauer beschreiben, was man will. Vielleicht sollte "So bleiben alle Vorkommastellen erhalten + mindestens 3 Nicht-0-Ziffern bleiben erhalten + .5 wird aufgerundet." ein Versuch sein, aber … das wirkt halt schon arg beliebig. Und wenn du jetzt genau begründen solltest, warum da zwar 12.3 (und nicht 12.0) aber 123.0 (und nicht 123.4) rauskommen sollte, müßtest du wahrscheinlich sowas sagen wie "
ja ich will das halt so…".
Wie auch immer:
An sich wirkt das Problem sehr ähnlich zum klassischen Problem, das man hat, wenn man z.B. einen Funktionsplotter implementieren will, und dort Achsenbeschriftungen vorkommen sollen. Egal, ob der dargestellte Bereich zwischen 0.00001 und 0.00002 liegt, oder zwischen 100000 und 200000 (oder zwischen 100000 und 100001 ?!), die Achsenbeschriftung soll „schön aussehen“ und „irgendwie passen“.
Und… da ich schonmal sowas gemacht habe, habe ich auch sowas mal versucht. Der Code liegt unter Viewer/Axes.java at master · javagl/Viewer · GitHub . Da du aus irgendeinem Grund eine Stelle mehr wolltest, ist der Code hier mal angepasst:
import java.util.Locale;
public class AxesFormattingTest
{
public static void main(String[] args)
{
testFormat();
}
private static void testFormat()
{
testFormat(1.23456);
testFormat(12.3456);
testFormat(123.456);
testFormat(1234.56);
testFormat(12345.6);
testFormat(0.123456);
testFormat(0.0123456);
testFormat(0.00123456);
testFormat(0.000123456);
}
private static void testFormat(double value)
{
String formatString = formatStringForBW(value);
String s = String.format(Locale.ENGLISH, formatString, value);
System.out.println("For "+value+" format "+formatString+" gives "+s);
}
/**
* Modified for byte-welt.net post:
*
* Returns a format string that can be used in <code>String#format</code>
* to format values of the given order. The exact meaning of this is
* intentionally left unspecified, but for numbers that are "reasonable"
* to be displayed as decimal numbers (without scientific notation),
* this function will return a format with the "appropriate" number of
* decimal digits in order to format axis labels.
*
* @param order The order
* @return The format string
*/
static String formatStringForBW(double order)
{
if (order < 1e-100 || !Double.isFinite(order))
{
return "%f";
}
double exponent = Math.floor(Math.log10(order));
int digits = (int)Math.abs(exponent);
if (order >= 1.0)
{
digits = 0;
}
digits += 1; // For BW
String result = "%."+digits+"f";
return result;
}
}
Die Ausgabe ist
For 1.23456 format %.1f gives 1.2
For 12.3456 format %.1f gives 12.3
For 123.456 format %.1f gives 123.5
For 1234.56 format %.1f gives 1234.6
For 12345.6 format %.1f gives 12345.6
For 0.123456 format %.2f gives 0.12
For 0.0123456 format %.3f gives 0.012
For 0.00123456 format %.4f gives 0.0012
For 1.23456E-4 format %.5f gives 0.00012
Vielleicht ist das mit der Stelleberechnung per log10
zumindest eine Inspiration.
- Über Performance brauchen wir im Vergleich zu
BigDecimal
, String#format
und Regex (
) ja vermutlich nicht zu reden.
- Was bei negativen Zahlen rauskommt, auch nicht (BTW: Die
order
bei mir ist, wie der Name schon sagt, nicht die zu formatierende Zahl selbst - d.h. die Funktion wird nur mit postitiven Zahlen aufgerufen, und liefert nur den Format-String)
- Darüber, was auf einem Rechner mit anderer
Locale
rauskommt, wenn man s.indexOf(',')
macht, auch nicht.
- Über solchen irritierend-haarsträubend-planlos-beliebig-murksigen Firlefanz wie
if (3 - a < 0)
(vs. if (a > 3)
) eigentlich auch nicht.
Bleibt noch was übrig, worüber man reden müßte? Nah, für mich im Moment nicht.