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

后言

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

相关推荐
世俗ˊ22 分钟前
CSS入门笔记
前端·css·笔记
子非鱼92122 分钟前
【前端】ES6:Set与Map
前端·javascript·es6
6230_26 分钟前
git使用“保姆级”教程1——简介及配置项设置
前端·git·学习·html·web3·学习方法·改行学it
想退休的搬砖人35 分钟前
vue选项式写法项目案例(购物车)
前端·javascript·vue.js
加勒比海涛1 小时前
HTML 揭秘:HTML 编码快速入门
前端·html
啥子花道1 小时前
Vue3.4 中 v-model 双向数据绑定新玩法详解
前端·javascript·vue.js
麒麟而非淇淋1 小时前
AJAX 入门 day3
前端·javascript·ajax
茶茶只知道学习1 小时前
通过鼠标移动来调整两个盒子的宽度(响应式)
前端·javascript·css
清汤饺子1 小时前
实践指南之网页转PDF
前端·javascript·react.js
蒟蒻的贤1 小时前
Web APIs 第二天
开发语言·前端·javascript