formatnumber(格式化数字)
简述:用于格式化数字文本或类数字的值,支持高精度计算、去科学计数法、控制大小范围、整数补零、补充千分位符号、进制基数转换 (开发中)。
兼容:最低需支持 ES6 环境,补零或高精度计算时需支持 ES7 环境,BigInt 类型数值运算时需支持 ES10 环境。
特性:此方法执行运算的时间复杂度在 O(n) 内,执行效率较优,适合作为通用工具函数使用。
/**
* 格式化数字
* @description 支持高精度格式化,可去除科学计数法,精度保留至无限
* @param {*} value 输入源
* @param {Object} [options] 配置项
* @param {Number} [options.min] 最小值
* @param {Number} [options.max] 最大值
* @param {Number} [options.precision] 数字精度 (结果保留的浮点位数)
* @param {Number} [options.sumprecision] 算术精度 (计算结果的实际精度)
* @param {*} [options.defaultValue] 数字无效时的默认值
* @param {Boolean} [options.defaultMinMax] 默认值是否使用最小值或最大值 ( true: 默认值,存在最小或最大值时默认使用 | false: 不使用 )
* @param {Number} [options.zeroFill] 是否补零 ( 默认不补零 | Number: 自定义长度补零 )
* @param {Boolean} [options.milFill] 是否补充千分位符号 ( 默认值不使用 | true: 使用 )
* @return {String}
*/
function formatNumber(value, options) {
let { min, max, precision, sumPrecision, defaultMinMax = true, zeroFill, milFill } = options || {}
let result = value, defaultValue = options && 'defaultValue' in options ? options.defaultValue : ''
if (!(
(typeof result == 'number' || typeof result == 'string' && result !== '') && !isNaN(result) ||
typeof result == 'bigint' && (result = String(result))
)) return defaultValue
if (min != null && result < min) {
if (!defaultMinMax) return defaultValue; result = min
} else if (max != null && result > max) {
if (!defaultMinMax) return defaultValue; result = max
}
if (!isFinite(result)) return defaultValue
if (/0(b|o|x)/i.test(result)) result = String((typeof BigInt == 'function' ? BigInt : Number)(result))
if (sumPrecision != null && (precision == null || precision > sumPrecision)) result = numToFixed(result, sumPrecision)
result = numToFixed(result, precision)
if (zeroFill > 0 || milFill) {
let { 1: minus = '', 2: int = '', 3: any = '' } = /^(-?)(\d )(.*)/.exec(result) || {}
if (zeroFill > int.length) int = `${''.padEnd(zeroFill - int.length, 0)}${int}`
if (milFill) {
let r = '', s = 3, i = int.length
while ((i -= s) > -s) r = `${int.slice(i > 0 ? i : 0, i s)}${r ? ',' : ''}${r}`
int = r
}
result = `${minus}${int}${any}`
}
return result
}
/**
* 高精度小数取舍
* @param {Number} value 输入源
* @param {Number} [precision] 数字精度 (可保留的浮点位数,为空时仅精度化不进行取舍)
* @return {String}
*/
function numToFixed(value, precision) {
if (!isFinite(value)) return String( value)
let reg = /^(-?)0*(\d*)(\.?)(\d*?)0*(e(-|\ )?(\d ))?$/i
let { 1: minus = '', 2: int = '', 4: dec = '', 6: dir, 7: fe } = reg.exec(value) || {}
if (minus && !(int || dec)) minus = ''
if (fe > 0 && (int || dec)) {
if (dir != '-') {
let df = fe - dec.length
int = df < 0 ? `${int}${dec.slice(0, df)}` : `${int}${dec}${''.padEnd(df, 0)}`
dec = df < 0 ? dec.slice(df) : ''
} else {
let df = fe - int.length
dec = df < 0 ? `${int.slice(-df)}${dec}` : `${''.padEnd(df, 0)}${int}${dec}`
int = df < 0 ? int.slice(0, -df) : ''
}
}
if (precision != null) {
precision = Math.max(Math.floor(precision), 0) || 0
if (precision >= dec.length) {
dec = dec.padEnd(precision, 0)
} else {
let grd = dec[precision] > 4; dec = dec.slice(0, precision)
if (grd) {
let r = '', b = `${int || 0}${dec}`, d = dec.length, i = b.length
while (--i >= 0) {
if (b[i] < 9) {
r = `${b.slice(0, i)}${ b[i] 1}${r}`; break
} else {
r = `${i == 0 ? '1' : ''}0${r}`
}
}
int = d ? r.slice(0, -d) : r
dec = d ? r.slice(-d) : ''
}
}
}
return `${minus}${int || 0}${dec ? `.${dec}` : ''}`
}
使用示例
formatNumber(), formatNumber(''), formatNumber('abc'), formatNumber(null)
// => ''
formatNumber(123)
// => '123'
formatNumber(123n)
// => '123'
formatNumber('123.00')
// => '123'
formatNumber('0b0101010')
// => '42'
formatNumber('0o1234567')
// => '342391'
formatNumber('0x1234abc')
// => '19090108'
formatNumber('-00123.45e 5')
// => '-12345000'
formatNumber('123.45000e-5')
// => '0.0012345'
formatNumber('123.45600', { precision: 2 })
// => '123.46'
formatNumber('123.45678', { precision: 3, min: 100, max: '110.50' })
// => '110.500'
formatNumber('abc', { defaultValue: null })
// => null
formatNumber(100, { min: 150, max: 200, defaultValue: 'abc', defaultMinMax: true })
// => '150'
formatNumber(300, { min: 150, max: 200, defaultValue: 'abc', defaultMinMax: false })
// => 'abc'
formatNumber('123.456', { zeroFill: 10 })
// => '0000000123.456'
formatNumber('12345678901234.56789', { milFill: true })
// => '12,345,678,901,234.56789'
String(Number('0.00000010200'))
// => '1.02e-7'
formatNumber('0.00000010200')
// => '0.000000102'
String(Number('0x1234567890abcdf123'))
// => '335812727627494300000'
formatNumber('0x1234567890abcdf123')
// => '335812727627494322467'
String(Number('12345.678901234567890'))
// => '12345.678901234567'
formatNumber('12345.678901234567890')
// => '12345.67890123456789'
String(Number('12345.678901234567890').toFixed(20))
// => '12345.67890123456709261518'
formatNumber('12345.678901234567890', { precision: 20 })
// => '12345.67890123456789000000'
String(Number('12345.678901234567890e30').toFixed(4))
// => '1.234567890123457e 34'
formatNumber('12345.678901234567890e30', { precision: 4 })
// => '12345678901234567890000000000000000.0000'
formatNumber('-12345.6789012345678901234567890e19', { zeroFill: 28, milFill: true })
// => '-0,000,123,456,789,012,345,678,901,234.56789'
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved