-
-
Notifications
You must be signed in to change notification settings - Fork 149
/
float.ts
66 lines (61 loc) · 1.66 KB
/
float.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import { memoizeJ } from "@thi.ng/memoize";
import { Stringer } from "./api";
import { padLeft } from "./pad-left";
/**
* Returns `Stringer` which formats numbers to given precision.
* Exceptions:
*
* - NaN => "NaN"
* - Infinity => "+/-∞"
*
* @param len number of fractional digits
* @kind function
*/
export const float: (prec: number) => Stringer<number> = memoizeJ(
(prec) => (x: number) => nanOrInf(x) || x.toFixed(prec)
);
/**
* Similar to `float`, returns `Stringer` which formats numbers to given
* character width & precision. Uses scientific notation if needed.
*
* Default precision: 3 fractional digits
*/
export const floatFixedWidth: (
width: number,
prec?: number
) => Stringer<number> = memoizeJ((width, prec = 3) => {
const l = width - prec - 1;
const pl = Math.pow(10, l);
const pln = -Math.pow(10, l - 1);
const pr = Math.pow(10, -(prec - 1));
const pad = padLeft(width);
return (x: number) => {
const ax = Math.abs(x);
return pad(
nanOrInf(x) ||
(x === 0
? "0"
: ax < pr || ax >= pl
? exp(x, width)
: x.toFixed(prec - (x < pln ? 1 : 0)))
);
};
});
const exp = (x: number, w: number) =>
x.toExponential(
Math.max(
w -
4 -
(Math.log(Math.abs(x)) / Math.LN10 >= 10 ? 2 : 1) -
(x < 0 ? 1 : 0),
0
)
);
const nanOrInf = (x: number) =>
isNaN(x)
? "NaN"
: x === Infinity
? "+∞"
: x === -Infinity
? "-∞"
: undefined;