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

后言

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

相关推荐
恋猫de小郭17 分钟前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅7 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60618 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了8 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅8 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅8 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅9 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment9 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅9 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊9 小时前
jwt介绍
前端