75 lines
2.9 KiB
Plaintext
Executable File
75 lines
2.9 KiB
Plaintext
Executable File
import { repeat, getMagnitude } from '../utils';
|
|
export function ToRawPrecision(x, minPrecision, maxPrecision) {
|
|
var p = maxPrecision;
|
|
var m;
|
|
var e;
|
|
var xFinal;
|
|
if (x === 0) {
|
|
m = repeat('0', p);
|
|
e = 0;
|
|
xFinal = 0;
|
|
}
|
|
else {
|
|
var xToString = x.toString();
|
|
// If xToString is formatted as scientific notation, the number is either very small or very
|
|
// large. If the precision of the formatted string is lower that requested max precision, we
|
|
// should still infer them from the formatted string, otherwise the formatted result might have
|
|
// precision loss (e.g. 1e41 will not have 0 in every trailing digits).
|
|
var xToStringExponentIndex = xToString.indexOf('e');
|
|
var _a = xToString.split('e'), xToStringMantissa = _a[0], xToStringExponent = _a[1];
|
|
var xToStringMantissaWithoutDecimalPoint = xToStringMantissa.replace('.', '');
|
|
if (xToStringExponentIndex >= 0 &&
|
|
xToStringMantissaWithoutDecimalPoint.length <= p) {
|
|
e = +xToStringExponent;
|
|
m =
|
|
xToStringMantissaWithoutDecimalPoint +
|
|
repeat('0', p - xToStringMantissaWithoutDecimalPoint.length);
|
|
xFinal = x;
|
|
}
|
|
else {
|
|
e = getMagnitude(x);
|
|
var decimalPlaceOffset = e - p + 1;
|
|
// n is the integer containing the required precision digits. To derive the formatted string,
|
|
// we will adjust its decimal place in the logic below.
|
|
var n = Math.round(adjustDecimalPlace(x, decimalPlaceOffset));
|
|
// The rounding caused the change of magnitude, so we should increment `e` by 1.
|
|
if (adjustDecimalPlace(n, p - 1) >= 10) {
|
|
e = e + 1;
|
|
// Divide n by 10 to swallow one precision.
|
|
n = Math.floor(n / 10);
|
|
}
|
|
m = n.toString();
|
|
// Equivalent of n * 10 ** (e - p + 1)
|
|
xFinal = adjustDecimalPlace(n, p - 1 - e);
|
|
}
|
|
}
|
|
var int;
|
|
if (e >= p - 1) {
|
|
m = m + repeat('0', e - p + 1);
|
|
int = e + 1;
|
|
}
|
|
else if (e >= 0) {
|
|
m = "".concat(m.slice(0, e + 1), ".").concat(m.slice(e + 1));
|
|
int = e + 1;
|
|
}
|
|
else {
|
|
m = "0.".concat(repeat('0', -e - 1)).concat(m);
|
|
int = 1;
|
|
}
|
|
if (m.indexOf('.') >= 0 && maxPrecision > minPrecision) {
|
|
var cut = maxPrecision - minPrecision;
|
|
while (cut > 0 && m[m.length - 1] === '0') {
|
|
m = m.slice(0, -1);
|
|
cut--;
|
|
}
|
|
if (m[m.length - 1] === '.') {
|
|
m = m.slice(0, -1);
|
|
}
|
|
}
|
|
return { formattedString: m, roundedNumber: xFinal, integerDigitsCount: int };
|
|
// x / (10 ** magnitude), but try to preserve as much floating point precision as possible.
|
|
function adjustDecimalPlace(x, magnitude) {
|
|
return magnitude < 0 ? x * Math.pow(10, -magnitude) : x / Math.pow(10, magnitude);
|
|
}
|
|
}
|