Commit | Line | Data |
---|---|---|
3f5430db MM |
1 | package net.mattmccutchen.measurements; |
2 | ||
3 | import java.util.*; | |
4 | ||
5 | public class Unit { | |
3a3b5f3c MM |
6 | public static final Unit SECOND = new Unit("s" , 1.0, 1, 0, 0, 0, 0, 0); |
7 | public static final Unit METER = new Unit("m" , 1.0, 0, 1, 0, 0, 0, 0); | |
8 | public static final Unit GRAM = new Unit("g" , 1.0, 0, 0, 1, 0, 0, 0); | |
9 | public static final Unit COULOMB = new Unit("coul", 1.0, 0, 0, 0, 1, 0, 0); | |
10 | public static final Unit KELVIN = new Unit("K" , 1.0, 0, 0, 0, 0, 1, 0); | |
11 | public static final Unit MOLE = new Unit("mol" , 1.0, 0, 0, 0, 0, 0, 1); | |
3f5430db MM |
12 | |
13 | public static final Unit[] basicUnits = new Unit[] { | |
3a3b5f3c | 14 | SECOND, METER, GRAM, COULOMB, KELVIN, MOLE, |
3f5430db MM |
15 | }; // Don't mutate |
16 | ||
3a3b5f3c MM |
17 | public static final Unit PERCENT = new Unit("%", 1e-2, 0, 0, 0, 0, 0, 0); |
18 | public static final Unit NEWTON = new Unit("N", 1e+3,-2, 1, 1, 0, 0, 0); | |
19 | public static final Unit JOULE = new Unit("J", 1e+3,-2, 2, 1, 0, 0, 0); | |
20 | public static final Unit WATT = new Unit("W", 1e+3,-3, 2, 1, 0, 0, 0); | |
21 | public static final Unit VOLT = new Unit("V", 1e+3,-2, 2, 1,-1, 0, 0); | |
22 | public static final Unit AMP = new Unit("A", 1.0 ,-1, 0, 0, 1, 0, 0); | |
23 | public static final Unit LITER = new Unit("L", 1e-3, 0, 3, 0, 0, 0, 0); | |
3f5430db MM |
24 | |
25 | public static final Unit[] allUnits = new Unit[] { | |
3a3b5f3c MM |
26 | SECOND, METER, GRAM, COULOMB, KELVIN, MOLE, |
27 | PERCENT, NEWTON, JOULE, WATT, VOLT, AMP, LITER, | |
3f5430db MM |
28 | }; // Don't mutate |
29 | ||
30 | public final String symbol; | |
31 | public final double factor; | |
32 | public final int[] powers; // Don't mutate | |
33 | ||
34 | private Unit(String symbol, double factor, int... powers) { | |
35 | this.symbol = symbol; | |
36 | this.factor = factor; | |
37 | this.powers = powers; | |
38 | } | |
39 | ||
40 | private static final Map<String, Unit> unitsBySymbol; // Don't mutate | |
41 | private static final Map<Character, Double> prefixes; // Don't mutate | |
42 | ||
43 | public static Unit lookupBySymbol(String symbol) { | |
44 | Unit u = unitsBySymbol.get(symbol); | |
45 | if (u != null) | |
46 | return u; | |
47 | char pfx = symbol.charAt(0); | |
48 | symbol = symbol.substring(1); | |
49 | u = unitsBySymbol.get(symbol); | |
50 | Double mult1 = prefixes.get(pfx); | |
51 | if (u != null && mult1 != null) | |
52 | return new Unit(symbol, u.factor * mult1, u.powers); | |
53 | return null; | |
54 | } | |
55 | ||
56 | static { | |
57 | unitsBySymbol = new LinkedHashMap<String, Unit>(); | |
58 | for (Unit u : allUnits) | |
59 | unitsBySymbol.put(u.symbol, u); | |
60 | ||
61 | prefixes = new LinkedHashMap<Character, Double>(); | |
62 | prefixes.put('k', 1e+03); | |
63 | prefixes.put('M', 1e+06); | |
64 | prefixes.put('G', 1e+09); | |
65 | prefixes.put('T', 1e+12); | |
66 | prefixes.put('P', 1e+15); | |
67 | prefixes.put('E', 1e+18); | |
68 | prefixes.put('Z', 1e+21); | |
69 | prefixes.put('Y', 1e+24); | |
3a3b5f3c | 70 | prefixes.put('c', 1e-02); |
3f5430db MM |
71 | prefixes.put('m', 1e-03); |
72 | prefixes.put('u', 1e-06); // micro -> u: oh well | |
73 | prefixes.put('n', 1e-09); | |
74 | prefixes.put('p', 1e-12); | |
75 | prefixes.put('f', 1e-15); | |
76 | prefixes.put('a', 1e-18); | |
77 | prefixes.put('z', 1e-21); | |
78 | prefixes.put('y', 1e-24); | |
79 | } | |
80 | ||
81 | public static Unit parseUnitString(String ustr) { | |
82 | double fctr = 1; | |
83 | int[] up = new int[Unit.basicUnits.length]; | |
84 | StringTokenizer unitT = new StringTokenizer(ustr, " */", true); | |
85 | boolean invert = false; | |
86 | while (unitT.hasMoreTokens()) { | |
87 | String tok = unitT.nextToken(); | |
88 | if (tok.equals("/")) { | |
89 | invert = !invert; | |
90 | continue; | |
91 | } else if (tok.equals(" ") || tok.equals("*")) | |
92 | continue; | |
93 | int caret = tok.indexOf('^'); | |
94 | String symbol; | |
95 | int power; | |
96 | if (caret == -1) { | |
97 | power = 1; | |
98 | symbol = tok; | |
99 | } else { | |
100 | power = Integer.parseInt(tok.substring(caret + 1)); | |
101 | symbol = tok.substring(0, caret); | |
102 | } | |
103 | Unit unit = Unit.lookupBySymbol(symbol); | |
104 | if (unit == null) | |
105 | throw new NullPointerException(); | |
106 | if (invert) | |
107 | power = -power; | |
108 | fctr *= Math.pow(unit.factor, power); | |
109 | for (int i = 0; i < Unit.basicUnits.length; i++) | |
110 | up[i] += power * unit.powers[i]; | |
111 | } | |
112 | return new Unit(ustr, fctr, up); | |
113 | } | |
114 | } |