Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
import { roundFloat } from "./math_round_float.ts"; ← from math.round-float ^1.0.0 · built alongside by fune
const POW10 = [1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12];
/**
* A float as decimal text, never in exponent form and never "-0".
*
* String(x), str(x) and Rust's Display disagree about floats: 1e21, 1e-7 and
* 2.0 print differently in each. So the number is rounded once, turned into a
* whole count of 10^-decimals units, and the digits of that integer are laid
* out by hand.
*/
export function formatDecimal(value: number, decimals: number, trimZeros: boolean, groupSeparator: string): string {
const rounded = roundFloat(value, decimals);
const scaled = Math.abs(rounded) * POW10[decimals];
if (scaled >= 1e15) {
throw new RangeError(`value is too large to format at ${decimals} decimal places, received ${value}`);
}
// rounded is within half an ulp of a whole number of units; below 10^15 the
// product cannot drift as far as the next one, so rounding recovers it.
const units = roundFloat(scaled, 0);
let digits = String(units);
while (digits.length < decimals + 1) digits = "0" + digits;
const whole = digits.slice(0, digits.length - decimals);
let fraction = digits.slice(digits.length - decimals);
if (trimZeros) {
let end = fraction.length;
while (end > 0 && fraction[end - 1] === "0") end--;
fraction = fraction.slice(0, end);
}
let grouped = "";
for (let i = 0; i < whole.length; i++) {
if (i > 0 && (whole.length - i) % 3 === 0) grouped += groupSeparator;
grouped += whole[i];
}
const body = fraction.length > 0 ? grouped + "." + fraction : grouped;
return units > 0 && rounded < 0 ? "-" + body : body;
}