后端:前端处理下极小或极大数下,我: 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);
        }
    }
}

后言

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

相关推荐
万少5 分钟前
第五款 HarmonyOS 上架作品 奇趣故事匣 来了
前端·harmonyos·客户端
OpenGL11 分钟前
Android targetSdkVersion升级至35(Android15)相关问题
前端
程序员鱼皮25 分钟前
Cursor 网页版来了,这下拉屎时也能工作了
计算机·ai·程序员·开发·项目·编程经验
rzl0226 分钟前
java web5(黑马)
java·开发语言·前端
Amy.Wang28 分钟前
前端如何实现电子签名
前端·javascript·html5
海天胜景30 分钟前
vue3 el-table 行筛选 设置为单选
javascript·vue.js·elementui
今天又在摸鱼30 分钟前
Vue3-组件化-Vue核心思想之一
前端·javascript·vue.js
蓝婷儿32 分钟前
每天一个前端小知识 Day 21 - 浏览器兼容性与 Polyfill 策略
前端
百锦再35 分钟前
Vue中对象赋值问题:对象引用被保留,仅部分属性被覆盖
前端·javascript·vue.js·vue·web·reactive·ref