Percentage Calculator — Java source
Calculate percentages three ways - X% of Y, X is what percent of Y, and the percentage change between two values. Runs entirely in your browser, with a shareable link.
This is the Java implementation — the same logic the interactive tool runs, in a shareable, citable form.
// percentage-calculator — Java port: three-way percentage math (X% of Y, X as % of Y, % change).
/** Pure percentage logic, ported from the canonical TS lib. Deterministic and
* side-effect free: every function returns null for non-finite input or an
* undefined result (a zero divisor) instead of throwing, and rounds to a
* configurable maximum number of decimals.
*
* Package-private because the display file is named java.java, not
* Percentage.java — the only way a public top-level class may sit in a
* mismatched filename is to drop the modifier. */
final class Percentage {
/** Rounding precision when an option is omitted, matching
* DEFAULT_MAX_DECIMALS in src/lib/percentage.ts. */
public static final int DEFAULT_MAX_DECIMALS = 2;
/** 2^-52 — identical to JavaScript's Number.EPSILON (Math.ulp(1.0)). */
private static final double JS_EPSILON = Math.ulp(1.0);
/** Options governing result precision. maxDecimals == null means
* "omitted" → the default, keeping an explicit 0 distinct from an unset
* value (the TS optional-field semantics). */
public record PercentOptions(Integer maxDecimals) {
/** The effective precision: the explicit option when set, otherwise
* the default. Mirrors the TS default-parameter behavior of round(). */
int resolve() {
return maxDecimals != null ? maxDecimals : DEFAULT_MAX_DECIMALS;
}
}
/** Round to at most maxDecimals places, absorbing binary float noise via
* the epsilon nudge (the classic 0.005 → 0.01 case). Non-finite values
* pass through unchanged so this function is total, exactly like the TS
* round(). */
public static double roundValue(double n, int maxDecimals) {
if (!Double.isFinite(n)) return n;
double factor = Math.pow(10, maxDecimals);
// Math.floor(x + 0.5) replicates JavaScript's Math.round (half toward
// +infinity). Math.round(long) is equivalent in effect but returns a
// long, losing the symmetric pass-through shape of the TS source.
return Math.floor((n + JS_EPSILON) * factor + 0.5) / factor;
}
/** X% of value: pct / 100 * value. null (the Java analogue of the TS
* null) when either input is non-finite. */
public static Double percentOf(double pct, double value, PercentOptions opts) {
if (!Double.isFinite(pct) || !Double.isFinite(value)) return null;
return roundValue((pct / 100) * value, opts.resolve());
}
/** What percentage part is of total: part / total * 100. null when total
* is 0 (undefined ratio) or either input is non-finite. */
public static Double whatPercent(double part, double total, PercentOptions opts) {
if (!Double.isFinite(part) || !Double.isFinite(total) || total == 0) return null;
return roundValue((part / total) * 100, opts.resolve());
}
/** Percentage change from from to to, measured against |from| so the
* result's sign reflects only the direction of change. null when from is
* 0 (no meaningful base) or either input is non-finite. */
public static Double percentChange(double from, double to, PercentOptions opts) {
if (!Double.isFinite(from) || !Double.isFinite(to) || from == 0) return null;
return roundValue(((to - from) / Math.abs(from)) * 100, opts.resolve());
}
public static void main(String[] args) {
PercentOptions omitted = new PercentOptions(null); // default → 2 decimals
PercentOptions zero = new PercentOptions(0); // explicit 0 ≠ omitted
show("15% of 200", percentOf(15, 200, omitted));
show("30 is what % of 200", whatPercent(30, 200, omitted));
show("change 40 -> 50", percentChange(40, 50, omitted));
show("change 50 -> 40", percentChange(50, 40, omitted));
show("15% of 37, 0 decimals", percentOf(15, 37, zero));
show("30 is what % of 0", whatPercent(30, 0, omitted));
show("change 0 -> 50", percentChange(0, 50, omitted));
}
/** Demo helper: print "null" for the undefined result, integers without a
* trailing ".0" (via the double formatter's minimal representation). */
private static void show(String label, Double v) {
String text = v == null ? "null" : String.valueOf(v);
System.out.printf("%-24s = %s%n", label, text);
}
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →