STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
jsformat.py
Go to the documentation of this file.
1"""Numbers written the way JavaScript writes them.
2
3Some files the apps hand out (EngineDesign's pressure-curve CSV, feed-twin's
4plot CSV) used to be built in the browser. Now the backends write them, and the
5files must not change in the move, so the numbers in them are printed by these:
6
7- ``js_number(x)`` is ``String(x)``: ECMAScript Number::toString over the
8 shortest round-trip digits, which Python's ``repr`` also produces;
9- ``js_to_fixed(x, d)`` is ``x.toFixed(d)``: the exact binary value rounded to
10 ``d`` places, a tie going away from zero (Python's own format rounds a tie to
11 even, so ``f"{0.125:.2f}"`` is ``0.12`` where JavaScript writes ``0.13``).
12"""
13
14from __future__ import annotations
15
16import math
17from decimal import ROUND_HALF_UP, Decimal
18from typing import Any
19
20
21def _special(f: float) -> str | None:
22 if math.isnan(f):
23 return "NaN"
24 if math.isinf(f):
25 return "Infinity" if f > 0 else "-Infinity"
26 return None
27
28
29def js_number(x: Any) -> str:
30 if x is None:
31 return "null"
32 if isinstance(x, bool):
33 return "true" if x else "false"
34 f = float(x)
35 special = _special(f)
36 if special:
37 return special
38 if f == 0:
39 return "0"
40 sign = "-" if f < 0 else ""
41 tup = Decimal(repr(abs(f))).normalize().as_tuple()
42 digits = "".join(map(str, tup.digits))
43 k = len(digits)
44 n = tup.exponent + k # value = 0.<digits> x 10^n
45 if k <= n <= 21:
46 return sign + digits + "0" * (n - k)
47 if 0 < n <= 21:
48 return sign + digits[:n] + "." + digits[n:]
49 if -6 < n <= 0:
50 return sign + "0." + "0" * (-n) + digits
51 e = n - 1
52 exp = ("+" if e >= 0 else "-") + str(abs(e))
53 return sign + (digits if k == 1 else digits[0] + "." + digits[1:]) + "e" + exp
54
55
56def js_to_fixed(x: Any, digits: int) -> str:
57 f = float(x)
58 special = _special(f)
59 if special:
60 return special
61 if abs(f) >= 1e21:
62 return js_number(f)
63 q = Decimal(f).quantize(Decimal(1).scaleb(-digits), rounding=ROUND_HALF_UP)
64 text = format(q, "f")
65 # -0.0001.toFixed(2) is "-0.00" in JavaScript: the sign stays.
66 if f < 0 and not text.startswith("-"):
67 text = "-" + text
68 return text
static emmc_status_t format(emmc_log_t *log)
Definition emmc_log.c:324
str js_number(Any x)
Definition jsformat.py:29
str|None _special(float f)
Definition jsformat.py:21
str js_to_fixed(Any x, int digits)
Definition jsformat.py:56