前端场景题

1、JS超过Number最大值如何处理?

在 JavaScript 中,Number 类型的最大值是 1.7976931348623157e+308,这个值可以通过 Number.MAX_VALUE 获取。这个最大值是由 JavaScript 的 Number 类型使用的 IEEE 754 双精度浮点数格式 决定的。


为什么 Number 的最大值是 1.7976931348623157e+308

  1. IEEE 754 双精度浮点数格式

    • JavaScript 的 Number 类型使用 IEEE 754 标准的 64 位双精度浮点数格式来表示数字。
    • 这 64 位被分为以下三部分:
      • 1 位符号位:表示数字的正负(0 表示正数,1 表示负数)。
      • 11 位指数位:表示数字的指数部分。
      • 52 位尾数位:表示数字的有效精度部分。
  2. 指数位的范围

    • 11 位指数位可以表示的范围是 02047(即 2^11 - 1)。
    • 为了支持正负指数,IEEE 754 使用 偏移值(bias),偏移值为 1023。因此,实际指数范围是 -1022+1023
    • 最大指数值是 1023
  3. 最大值的计算

    • 当指数位为最大值 1023 时,表示的数字是:
      1.1111111111111111111111111111111111111111111111111111(二进制) × 2^1023
      
    • 转换为十进制后,这个值约为 1.7976931348623157e+308
  4. 为什么不是更大的值?

    • 如果指数位超过 1023,IEEE 754 会将其解释为 特殊值,例如 Infinity(无穷大)。
    • 因此,1.7976931348623157e+308Number 类型能够表示的最大有限值。

Number 的最大安全整数:9007199254740991

虽然 Number 的最大值是 1.7976931348623157e+308,但 Number 类型能够精确表示的最大整数是 9007199254740991,这个值可以通过 Number.MAX_SAFE_INTEGER 获取。

为什么最大安全整数是 9007199254740991
  • IEEE 754 双精度浮点数的尾数部分有 52 位,因此可以精确表示的整数范围是:
    -2^53 + 1 到 +2^53 - 1
    
  • 2^53 - 1 的值是 9007199254740991
  • 超过这个范围的整数可能会丢失精度,因为尾数部分不足以精确表示这些整数。

总结:

  • Number 的最大值是 1.7976931348623157e+308,这是由 IEEE 754 双精度浮点数的指数范围决定的。
  • Number 的最大安全整数是 9007199254740991,这是由尾数部分的位数决定的。
  • 如果需要处理更大的整数或需要更高的精度,可以使用 BigInt 类型。

大数产生背景

  • 1、金融行业
  • 2、科学计算:计算机生成的数据可能会生成比较大的数
  • 3、数据分析: 公司在做大数据计算时可能会生成比较大的数

解决方案

  • 1、ES6的Bigint数据类型
    const a = BigInt("111111111111111111111111111111111111111111111111111111111111");
    // 或 const a = 111111111111111111111111111111111111111111111111111111111111n
    const b = BigInt("111111111111111111111111111111111111111111111111111111111111");
    const c = a + b;
    // 222222222222222222222222222222222222222222222222222222222222n
    

    注意:以下这种写法是错误的;BigInt里参数如果还是数字,那将会导致数字超过最大值,导致生成的Bigint值不准确

    const a = BigInt(111111111111111111111111111111111111111111111111111111111111);
    // 111111111111111115398901787910723492567390900178539566333952n   错误写法
    
  • 2、第三方库decimal.js库等
  • 3、字符串计算
function addLargeNumbers(num1, num2) {
   
   
  // 将两个数字转换为字符串,方便逐位操作
  let str1 = num1.toString();
  let str2 = num2.toString();

  // 补齐较短的数字,前面补零
  const maxLength = Math.max(str1.length, str2.length);
  str1 = str1.padStart(maxLength, '0');
  str2 = str2.padStart(maxLength, '0');

  let carry = 0; // 进位
  let result = ''; // 最终结果

  // 从最低位(字符串的末尾)开始逐位相加
  for (let i = maxLength - 1; i >= 0; i--) {
   
   
    const digit1 = parseInt(str1[i], 10); // 获取当前位的数字
    const digit2 = parseInt(str2[i], 10); // 获取当前位的数字

    // 计算当前位的和(包括进位)
    const sum = digit1 + digit2 + carry;
    const digitSum = sum % 10; // 当前位的值
    carry = Math.floor(sum / 10); // 计算进位

    // 将当前位的值拼接到结果中
    result = digitSum.toString() + result;
  }

  // 如果最后还有进位,拼接到结果前面
  if (carry > 0) {
   
   
    result = carry.toString() + result;
  }

  return result;
}

// 示例用法
const num1 = '123456789012345678901234567890';
const num2 = '987654321098765432109876543210';
const sum = addLargeNumbers(num1, num2);
console.log(sum); // 输出: 1111111110111111111011111111100
  • 4、限制用户输入比较大的值

2、如何解决页面请求接口大规模并发问题

2.1、请求队列

在这里队列分为两种。1、全部定义好队列后再发送请求. 2、定义一个空队列,每当想队列添加值的时候再发送请求

2.1.1 全部定义好队列后再发送请求

实现细节:

  • 1、定义好一个请求队列
  • 2、循环最大并发数,每循环一次就从队列头部shift出一条数据。拿到数据并执行发送请求sendAjax
  • 3、在sendAjax有结果时(finally),如果队列中还有数据,则继续从队列头部shift出一条数据。拿到数据并执行发送请求sendAjax

2.1.2 定义一个空队列,每当想队列添加值的时候再发送请求实现细节:

  • 1、定义一个空队列、定义当前正在执行的并发数
  • 2、每执行addQueue 则将数据push到队列;并执行队列函数
  • 3、在执行队列函数中判断队列是否还有数据?当前正在执行的并发数 是否 小于 最大并发数?
    • 是: 队列头部shift出一条数据。拿到数据并执行发送请求sendAjax
  • 4、在sendAjax有结果时(finally),执行步骤 3
        class ReqestQueue {
   
   
            queues = [] // 请求队列 (队列中放入返回Promise函数)
            maxConcurrent = 1 // 最大并发数
            currentConcurrent = 0 // 当前并发数
            constructor (maxConcurrent) {
   
   
                this.maxConcurrent = maxConcurrent
            }
            
            // 增加队列
            addQueue ({
    
     request, data }) {
   
   
                return new Promise((resolve, reject) => {
   
   
                    this.queues.push({
   
    request, data, resolve, reject })
                    this.processQueue()
                })
            }

            // 执行队列
            processQueue () {
   
   
                if (this.currentConcurrent >= this.maxConcurrent || this.queues.length <= 0) return false
                const queue = this.queues.shift()
                this.sendAjax(queue)
            }

            // 发送ajax
            sendAjax ({
    
     request, data, resolve, reject }) {
   
   
                this.currentConcurrent++
                request(data)
                    .then((res) => {
   
   
                        resolve(res)
                    })
                    .catch((err) => {
   
   
                        reject(err)
                    })
                    .finally(() => {
   
   
                        this.currentConcurrent--
                        this.processQueue()
                    })
            }
        }

        // 请求实例
        const reqestQueue = new ReqestQueue(3)
       for (let i = 0; i < 10; i++) {
   
   
            reqestQueue.addQueue
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值