116 lines
2.6 KiB
TypeScript
116 lines
2.6 KiB
TypeScript
import { supportBigInt } from './supportUtil';
|
|
|
|
/**
|
|
* Format string number to readable number
|
|
*/
|
|
export function trimNumber(numStr: string) {
|
|
let str = numStr.trim();
|
|
|
|
let negative = str.startsWith('-');
|
|
|
|
if (negative) {
|
|
str = str.slice(1);
|
|
}
|
|
|
|
str = str
|
|
// Remove decimal 0. `1.000` => `1.`, `1.100` => `1.1`
|
|
.replace(/(\.\d*[^0])0*$/, '$1')
|
|
// Remove useless decimal. `1.` => `1`
|
|
.replace(/\.0*$/, '')
|
|
// Remove integer 0. `0001` => `1`, 000.1' => `.1`
|
|
.replace(/^0+/, '');
|
|
|
|
if (str.startsWith('.')) {
|
|
str = `0${str}`;
|
|
}
|
|
|
|
const trimStr = str || '0';
|
|
const splitNumber = trimStr.split('.');
|
|
|
|
const integerStr = splitNumber[0] || '0';
|
|
const decimalStr = splitNumber[1] || '0';
|
|
|
|
if (integerStr === '0' && decimalStr === '0') {
|
|
negative = false;
|
|
}
|
|
|
|
const negativeStr = negative ? '-' : '';
|
|
|
|
return {
|
|
negative,
|
|
negativeStr,
|
|
trimStr,
|
|
integerStr,
|
|
decimalStr,
|
|
fullStr: `${negativeStr}${trimStr}`,
|
|
};
|
|
}
|
|
|
|
export function isE(number: string | number) {
|
|
const str = String(number);
|
|
|
|
return !Number.isNaN(Number(str)) && str.includes('e');
|
|
}
|
|
|
|
/**
|
|
* [Legacy] Convert 1e-9 to 0.000000001.
|
|
* This may lose some precision if user really want 1e-9.
|
|
*/
|
|
export function getNumberPrecision(number: string | number) {
|
|
const numStr = String(number);
|
|
|
|
if (isE(number)) {
|
|
let precision = Number(numStr.slice(numStr.indexOf('e-') + 2));
|
|
|
|
const decimalMatch = numStr.match(/\.(\d+)/);
|
|
if (decimalMatch?.[1]) {
|
|
precision += decimalMatch[1].length;
|
|
}
|
|
return precision;
|
|
}
|
|
|
|
return numStr.includes('.') && validateNumber(numStr)
|
|
? numStr.length - numStr.indexOf('.') - 1
|
|
: 0;
|
|
}
|
|
|
|
/**
|
|
* Convert number (includes scientific notation) to -xxx.yyy format
|
|
*/
|
|
export function num2str(number: number): string {
|
|
let numStr = String(number);
|
|
if (isE(number)) {
|
|
if (number > Number.MAX_SAFE_INTEGER) {
|
|
return String(supportBigInt() ? BigInt(number).toString() : Number.MAX_SAFE_INTEGER);
|
|
}
|
|
|
|
if (number < Number.MIN_SAFE_INTEGER) {
|
|
return String(supportBigInt() ? BigInt(number).toString() : Number.MIN_SAFE_INTEGER);
|
|
}
|
|
|
|
numStr = number.toFixed(getNumberPrecision(numStr));
|
|
}
|
|
|
|
return trimNumber(numStr).fullStr;
|
|
}
|
|
|
|
export function validateNumber(num: string | number) {
|
|
if (typeof num === 'number') {
|
|
return !Number.isNaN(num);
|
|
}
|
|
|
|
// Empty
|
|
if (!num) {
|
|
return false;
|
|
}
|
|
|
|
return (
|
|
// Normal type: 11.28
|
|
/^\s*-?\d+(\.\d+)?\s*$/.test(num) ||
|
|
// Pre-number: 1.
|
|
/^\s*-?\d+\.\s*$/.test(num) ||
|
|
// Post-number: .1
|
|
/^\s*-?\.\d+\s*$/.test(num)
|
|
);
|
|
}
|