后端:前端处理下极小或极大数下,我: emem 好

前言

前端项目中,平时不会出现非常大的数或极小数,所以大多时候不会担心数字的处理,最多补位,然后最近项目遇到用户可以在输入框输入8位小数,神奇的一幕就发生了,输入 0.00000001 就转化成 1e-8,因此,我们要解决的就是 极小或极大数 给转换成 科学计数法的情况,后端可能返回给你一个数字 0.00000001,我们获取就变成 1e-8,展示不可能给用户展示科学计数法的,所以我们需要含泪写个方法来格式化解决

需求

  • 满足四舍五入,有同学会说 toFixed就可以,但是它有时候不准
  • 支持科学计数法
  • 支持补位

用例

js 复制代码
console.log(round(11));
// 输出:11

console.log(round(11,2));
// 输出:11.00

console.log(round(1e20));
// 输出:100000000000000000000

console.log(round(1e-20));
// 输出:0.00000000000000000001

console.log(round(1.222e50));
// 输出:122200000000000000000000000000000000000000000000000

console.log(round(1.222e-20));
// 输出:0.00000000000000000001222

console.log(round(123.456));
// 输出:123.456

console.log(round(123.456, 0));
// 输出:123

console.log(round(123.456, 1));
// 输出:123.5

console.log(round(123.456, 2));
// 输出:123.46

console.log(round(123.456, 3));
// 输出:123.456

console.log(round(123.456, 4));
// 输出:123.4560

console.log(round(123.456, 5));
// 输出:123.45600

console.log(round(1e-8));
// 输出:0.00000001

console.log(round(1.23e5));
// 输出:123000.00

console.log(round(1.23e5,1));
// 输出:123000.0

console.log(round('1.23e5',2));
// 输出:123000.00

console.log(round(1.234567891234567e-16,20));
// 输出:0.00000000000000012346

console.log(round(123e+25,20));
// 输出:1230000000000000000000000000.00000000000000000000

console.log(round('1.23e5',2)) 
// 输出: 123000.00

这段代码是一个 JavaScript 函数,用于将给定的小数四舍五入到指定的位数。下面是函数的解释:

该函数接受两个参数:n 表示要进行四舍五入的小数,decimals 表示要保留的小数位数。如果 decimals 未提供,则返回原始数值 n。否则,使用数学运算将 n 四舍五入到指定的位数,并返回结果。

以下是一些测试用例,涵盖了各种场景:

  1. 测试正常四舍五入:
js 复制代码
console.log(round(3.14159, 2)); // 3.14
console.log(round(10.567, 1));  // 10.6
console.log(round(123.456, 0)); // 123
  1. 测试无需四舍五入的情况:
js 复制代码
console.log(round(5.0, 1));  // 5
console.log(round(100, 2));  // 100
console.log(round(7.89, 2)); // 7.89
  1. 测试负数的情况:
js 复制代码
console.log(round(-3.14159, 2)); // -3.14
console.log(round(-10.567, 1));  // -10.6
console.log(round(-123.456, 0)); // -123
  1. 测试不同位数的四舍五入:
js 复制代码
console.log(round(1234.5678, 3)); // 1234.568
console.log(round(987.654321, 5)); // 987.65432
  1. 测试未提供要四舍五入到的位数的情况:
js 复制代码
console.log(round(3.14159)); // 3.14159
console.log(round(10.567));  // 10.567
console.log(round(123.456)); // 123.456
  1. 测试非数字输入的情况:
js 复制代码
console.log(round('abc', 2)); // NaN
console.log(round(NaN, 2));    // NaN
console.log(round(undefined, 2)); // NaN

这些测试用例覆盖了正数、负数、整数、小数、不同的精度以及边界条件等情况,可以验证函数的正确性。

实现

js 复制代码
// 四舍五入到指定位数的函数
const round = function (n, dight) {
    // 将输入的数字转换为字符串
    n = Number(n).toString();

    // 如果是科学计算法
    if (n.includes('e')) {
        // 分离系数和指数
        let [coefficient, exponent] = n.split('e');

        // 如果系数是小数进行抹平
        if (coefficient.includes('.')) {
            const arr = coefficient.split('.');
            const dotLen = arr[1].length;
            exponent = exponent - dotLen;
            coefficient = coefficient.replace('.', '');
        }

        // 处理指数大于0的情况(整数部分)
        if (exponent > 0) {
            // 构造补零部分
            const end = '0'.repeat(exponent);
            // 合并系数和补零部分
            const rt = coefficient + end;
            // 如果指定保留小数位数,则返回带小数的结果
            if (dight) return rt + '.' + '0'.repeat(dight);
            // 如果补零位数大于系数位数,直接返回结果
            if (exponent > coefficient.length) return rt;
            // 补零位数小于等于系数位数,截取结果
            return (rt + '0'.repeat(dight)).slice(0, -1 * dight);
        } else if (exponent < 0) { // 处理指数小于0的情况(小数部分)
            // 补零形成小数
            n = '0.' + coefficient.padStart(-exponent, 0);
            // 如果未指定小数位数,直接返回结果
            if (dight === undefined) return n;
            // 四舍五入
            const r = (Math.round(n * 10 ** exponent / (10 ** (exponent - dight))) / 10 ** dight).toString();
            // 处理科学计数法结果
            if (r.includes('e')) {
                let [coefficient, exponent] = r.split('e'); 
                if (coefficient.includes('.')) {
                    const arr = coefficient.split('.');
                    const dotLen = arr[1].length;
                    exponent = exponent - dotLen;
                    coefficient = coefficient.replace('.', '');
                }
                // 返回补零形成的小数
                return '0.' + coefficient.padStart(-exponent, 0);
            } else {
                // 返回四舍五入后的结果
                return r;
            }
        }
    } else { // 非科学计算法
        if (n.includes('.')) { // 处理小数
            const arr = n.split('.');
            let dotLen = arr[1].length;
            // 补零保留小数位数
            if (dight > dotLen) return n.padEnd(n.length + dight - dotLen, '0');
            // 如果未指定小数位数,直接返回结果
            if (dight === undefined) return n;
            // 四舍五入
            const r = Math.round((n * (10 ** dotLen)) / (10 ** (dotLen - dight))) / (10 ** dight);
            return Number.isInteger(r) ?  r.toFixed(dight) : r;
        } else { // 处理整数
            // 保留小数位数
            return Number(n).toFixed(dight);
        }
    }
}

后言

希望对大家有用,如有疑问,欢迎留言,有更好的想法或建议,欢迎一起讨论

相关推荐
Myli_ing35 分钟前
HTML的自动定义倒计时,这个配色存一下
前端·javascript·html
dr李四维1 小时前
iOS构建版本以及Hbuilder打iOS的ipa包全流程
前端·笔记·ios·产品运营·产品经理·xcode
I_Am_Me_1 小时前
【JavaEE进阶】 JavaScript
开发语言·javascript·ecmascript
雯0609~1 小时前
网页F12:缓存的使用(设值、取值、删除)
前端·缓存
℘团子এ1 小时前
vue3中如何上传文件到腾讯云的桶(cosbrowser)
前端·javascript·腾讯云
学习前端的小z1 小时前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript
前端百草阁2 小时前
【TS简单上手,快速入门教程】————适合零基础
javascript·typescript
彭世瑜2 小时前
ts: TypeScript跳过检查/忽略类型检查
前端·javascript·typescript
FØund4042 小时前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html
Backstroke fish2 小时前
Token刷新机制
前端·javascript·vue.js·typescript·vue