|
|
@@ -6,7 +6,10 @@
|
|
|
*/
|
|
|
package net.ranides.assira.text;
|
|
|
|
|
|
+import java.util.IllegalFormatConversionException;
|
|
|
import java.util.Locale;
|
|
|
+import net.ranides.assira.collection.maps.IntHashMap;
|
|
|
+import net.ranides.assira.collection.maps.IntMap;
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
@@ -18,34 +21,8 @@ public final class FormatNumber {
|
|
|
/* utility class */
|
|
|
}
|
|
|
|
|
|
- public static class UnitPrefix {
|
|
|
-
|
|
|
- private final double v;
|
|
|
- private final String u;
|
|
|
-
|
|
|
- UnitPrefix(double v, String u) {
|
|
|
- this.v = v;
|
|
|
- this.u = u;
|
|
|
- }
|
|
|
-
|
|
|
- public double value() {
|
|
|
- return v;
|
|
|
- }
|
|
|
-
|
|
|
- public String text() {
|
|
|
- return u;
|
|
|
- }
|
|
|
-
|
|
|
- StringBuilder append(StringBuilder target, int padding, int precision, double value) {
|
|
|
- return target.append(
|
|
|
- String.format(Locale.ENGLISH,
|
|
|
- String.format("%%%d.%df%s", padding, precision, text()), value/value())
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- public static final UnitPrefix[] METRIC_PREFIX = new UnitPrefix[]{
|
|
|
+ // metric (SI)
|
|
|
+ private static final UnitPrefix[] MP = new UnitPrefix[]{
|
|
|
new UnitPrefix(Math.pow(1000, 8),"Y"),
|
|
|
new UnitPrefix(Math.pow(1000, 7),"Z"),
|
|
|
new UnitPrefix(Math.pow(1000, 6),"E"),
|
|
|
@@ -65,7 +42,8 @@ public final class FormatNumber {
|
|
|
new UnitPrefix(Math.pow(1000, -8),"y")
|
|
|
};
|
|
|
|
|
|
- public static final UnitPrefix[] METRIC_EXP = new UnitPrefix[]{
|
|
|
+ // metric (SI)
|
|
|
+ private static final UnitPrefix[] ME = new UnitPrefix[]{
|
|
|
new UnitPrefix(Math.pow(1000, 8),"E24"),
|
|
|
new UnitPrefix(Math.pow(1000, 7),"E21"),
|
|
|
new UnitPrefix(Math.pow(1000, 6),"E18"),
|
|
|
@@ -85,35 +63,106 @@ public final class FormatNumber {
|
|
|
new UnitPrefix(Math.pow(1000, -8),"E-24")
|
|
|
};
|
|
|
|
|
|
- public static final UnitPrefix[] BYTE_PREFIX = new UnitPrefix[]{
|
|
|
- new UnitPrefix(Math.pow(1024, 8),"Y"),
|
|
|
- new UnitPrefix(Math.pow(1024, 7),"Z"),
|
|
|
- new UnitPrefix(Math.pow(1024, 6),"E"),
|
|
|
- new UnitPrefix(Math.pow(1024, 5),"P"),
|
|
|
- new UnitPrefix(Math.pow(1024, 4),"T"),
|
|
|
- new UnitPrefix(Math.pow(1024, 3),"G"),
|
|
|
- new UnitPrefix(Math.pow(1024, 2),"M"),
|
|
|
- new UnitPrefix(Math.pow(1024, 1),"K"),
|
|
|
+ // binary: IEC 80000-13
|
|
|
+ private static final UnitPrefix[] BP = new UnitPrefix[]{
|
|
|
+ new UnitPrefix(Math.pow(1024, 8),"Yi"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 7),"Zi"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 6),"Ei"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 5),"Pi"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 4),"Ti"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 3),"Gi"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 2),"Mi"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 1),"Ki"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 0),""),
|
|
|
+ };
|
|
|
+
|
|
|
+ // binary: exponents
|
|
|
+ private static final UnitPrefix[] BE = new UnitPrefix[]{
|
|
|
+ new UnitPrefix(Math.pow(1024, 8),"B24"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 7),"B21"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 6),"B18"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 5),"B15"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 4),"B12"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 3),"B9"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 2),"B6"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 1),"B3"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 0),"B0"),
|
|
|
+ };
|
|
|
+
|
|
|
+ // binary: Knuth
|
|
|
+ private static final UnitPrefix[] BK = new UnitPrefix[]{
|
|
|
+ new UnitPrefix(Math.pow(1024, 8),"YY"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 7),"ZZ"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 6),"EE"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 5),"PP"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 4),"TT"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 3),"GG"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 2),"MM"),
|
|
|
+ new UnitPrefix(Math.pow(1024, 1),"KK"),
|
|
|
new UnitPrefix(Math.pow(1024, 0),""),
|
|
|
};
|
|
|
+
|
|
|
+ private static final IntMap<UnitPrefix[]> PREFIXES = new IntHashMap<>(
|
|
|
+ new int[]{ 'M', 'E', 'S', 'B', 'K' },
|
|
|
+ new UnitPrefix[][]{ MP, ME, BP, BE, BK }
|
|
|
+ );
|
|
|
|
|
|
- public static String asEngineer(int padding, int precision, UnitPrefix[] units, double value) {
|
|
|
- return asEngineer(new StringBuilder(), padding, precision, units, value).toString();
|
|
|
+ /**
|
|
|
+ * Supported formats (unit prefixes):
|
|
|
+ * <ul>
|
|
|
+ * <li>M (metric, SI prefix)</li>
|
|
|
+ * <li>E (metric, exponent)</li>
|
|
|
+ * <li>S (binary, IEC prefix)</li>
|
|
|
+ * <li>K (binary, Donald Knuth prefix)</li>
|
|
|
+ * <li>B (binary, exponent)</li>
|
|
|
+ * </ul>
|
|
|
+ * @param format "printf-compatible" number format, e.g {@code %2.5M}
|
|
|
+ * @param value
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static String asEngineer(String format, double value) {
|
|
|
+ return asEngineer(new StringBuilder(), format, value).toString();
|
|
|
}
|
|
|
|
|
|
- public static StringBuilder asEngineer(StringBuilder target, int padding, int precision, UnitPrefix[] units, double value) {
|
|
|
+ /**
|
|
|
+ * Supported formats (unit prefixes):
|
|
|
+ * <ul>
|
|
|
+ * <li>M (metric, SI prefix)</li>
|
|
|
+ * <li>E (metric, exponent)</li>
|
|
|
+ * <li>S (binary, IEC prefix)</li>
|
|
|
+ * <li>K (binary, Donald Knuth prefix)</li>
|
|
|
+ * <li>B (binary, exponent)</li>
|
|
|
+ * </ul>
|
|
|
+ * @param target
|
|
|
+ * @param format format string compatible with String#format.
|
|
|
+ * @param value
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static StringBuilder asEngineer(StringBuilder target, String format, double value) {
|
|
|
if(value < 0) {
|
|
|
target.append('-');
|
|
|
- return asEngineer(target, padding, precision, units, -value);
|
|
|
+ return asEngineer(target, format, -value);
|
|
|
+ }
|
|
|
+
|
|
|
+ char fu = format.charAt(format.length()-1);
|
|
|
+
|
|
|
+ UnitPrefix[] au = PREFIXES.get(fu);
|
|
|
+ if(null == au) {
|
|
|
+ throw new IllegalFormatConversionException(fu, UnitPrefix.class);
|
|
|
}
|
|
|
- UnitPrefix c = units[0];
|
|
|
- for (UnitPrefix u : units) {
|
|
|
+
|
|
|
+ UnitPrefix c = au[0];
|
|
|
+ for (UnitPrefix u : au) {
|
|
|
c = u;
|
|
|
if (value > c.value()) {
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
- return c.append(target, padding, precision, value);
|
|
|
+
|
|
|
+ String fs = format.substring(0, format.length()-1)+"f";
|
|
|
+ return target
|
|
|
+ .append(String.format(Locale.ENGLISH, fs, value/c.value()))
|
|
|
+ .append(c.text());
|
|
|
}
|
|
|
|
|
|
public static String group(int value) {
|
|
|
@@ -134,5 +183,25 @@ public final class FormatNumber {
|
|
|
}
|
|
|
return ret.toString();
|
|
|
}
|
|
|
+
|
|
|
+ private static class UnitPrefix {
|
|
|
+
|
|
|
+ private final double v;
|
|
|
+ private final String u;
|
|
|
+
|
|
|
+ UnitPrefix(double v, String u) {
|
|
|
+ this.v = v;
|
|
|
+ this.u = u;
|
|
|
+ }
|
|
|
+
|
|
|
+ public double value() {
|
|
|
+ return v;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String text() {
|
|
|
+ return u;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
}
|