四道有意思的考题

前言

今天总结一下前几天所学到的个四个考题,快来看看你能不能全部答对吧!

字符串相加

有人会说数字求和不是很简单吗,加法谁不会算呢?

虽然说加法算数确实不能,但是如果数字是一个非常非常大,简单的加法就无法得到正确的结果了。我们需要采用特殊的方法计算正确的结果。

当数字非常大的时候,如果使用普通的加法,是无法得到正确结果的,超出了计算范围。所以,这时候就需要我们把数字转成字符串,然后从末尾进行相加。这种题目是高精度的板子题也不算太难,只需要把加法过程用代码表示出来,就能解出来。

js 复制代码
/**
 * @param {string} num1
 * @param {string} num2
 * @return {string}
 */
var addStrings = function(num1, num2) {
    let i=num1.length-1  //从后往前加
    let j=num2.length-1
    let carry=0
    let res=[]
    while(i>=0||j>=0||carry!==0){
        let dig1=i>=0?num1.charAt(i)-'0':0
        let dig2=j>=0?num2.charAt(j)-'0':0
        let sum=dig1+dig2+carry
        res.push(sum%10)
        carry=Math.floor(sum/10)
        i--
        j--
    }
    return res.reverse().join('')
};

0.1 + 0.2===0.3

这个问题也是非常常见,也非常简单的,结果是false。为什么会不相等呢?在我们的日常生活里,0.1+0.2计算得到0.3是非常简单且不用思考的。但是,计算机的计算方式和我们正常的计算方式是有差异的。

首先,JS要把0.1 和 0.2转换成对应的二进制。

0.1: 0 01111111011 1001100110011001100110011001100110011001100110011010 0.2:0 01111111100 1001100110011001100110011001100110011001100110011010

然后把两个进行相加,得到结果再转换成十进制,0.3000000000000004。显然和0.3不相等,最终返回false

0 01111111101 0011001100110011001100110011001100110011001100111010

想必这样解释应该是非常易懂了。要是问起来为什么不等于0.3,我们只需要回答计算机采用了IEEE754编码存储浮点数,无法精确表示十进制的数字。那么,如何实现0.1+0.2==0.3呢?

在数学里,判断两个数字是否相等,我们可以采用让二者进行相减,得到的结果和一个极小的数字进行比较。要是比极小的数字还小,那么就可以认为两个数字相等。而Number里面有个Number.EPSILON表示非常小的数。

js 复制代码
function isSame(num1,num2){
    return (num1-num2)<Number.EPSILON
}

红包算法

抢红包是一件非常常见的事情,请你设计一个红包算法。

这个抢红包算法,看似非常简单,只需要生成随机数就行。但是,还是有很多细节需要考虑的。

看着如此多的要求,设计一个好的红包算法还是有点难度的。

首先,需要有个红包数组来存储,红包数组的长度为红包总个数。

我们生成随机数,只需要生成n-1个。最后一个红包的金额就是最终剩下的金额。我们还需确保生成的随机数至少是0.01,总可不能出现一个空红包吧?

其次,我们要让这个算法生成的随机数组不能太平均,也不能差异太大。 最后把生成的随机数组返回即可。

ini 复制代码
function redPackets(total, num) {
    const res = [];
    let restAmount = total;
    let restNum = num;
    for (let i = 0; i < num - 1; i++) {
        // 每个红包的最小金额为 0.01
        let max = (restAmount / restNum) * 2;
        let amount = Math.random() * max;
        amount = Math.floor(amount * 100) / 100; // 保留两位小数
        if (amount < 0.01) amount = 0.01;
        restAmount -= amount;
        restAmount = Math.floor(restAmount * 100) / 100;
        restNum--;
        res.push(amount);
    }
    // 最后一个红包为剩余金额,保留两位小数
    res.push(Math.floor(restAmount * 100) / 100);
    return res;
}

for (let i = 0; i < 10; i++) {
    console.log([...redPackets(100, 10)]);
}

奇怪的输出

"1","2","3"\].map(parseInt) 的输出结果是什么?

看到这题,我们很容易误认为输出的结果会是1,2,3。要是回答了这个结果,面试官可能就让你回家等通知了。

实际上这个结果是[1,NAN,NAN],是不是和你想的完全不一样。那么为什么会出现这个结果呢?

就让我们再看仔细看Map函数和parseInt函数吧。
Map函数 :在绝大多数情况下,我们用map都只用它的第一个参数,即当前遍历的元素。而map还有第二个参数(当前的下标),第三个参数(数组本身)。
parseInt函数:parseInt(string,radix)函数有两个参数,第一个参数是传入的字符串,而第二个参数就是用来描述传入字符串是几进制。如果没有传入第二个参数,那么它会根据以下规则自动判断string是几进制。

  • 如果字符串string以'0x'开头,parseInt()会把string的其余部分解析为十六进制的整数
  • 如果string以0开头,那么ECMAScipt v3允许parseInt()的一个实现把其后的字符串解析为八进制或十六进制的数字。
  • 如果string以1~9的数字开头,parseInt()将把它解析为十进制的数字。

根据以上规则,我们来分析这个遍历过程: 第一次循环:

javascript 复制代码
parseInt('1',0) //参数:'1',进制默认为十进制,返回结果1

第二次循环:

javascript 复制代码
parseInt('2',1) //参数:'2',进制为一进制,由于没有一进制,所以返回NAN

第三次循环:

javascript 复制代码
parseInt('3',2) //参数:'3',进制为二进制,3无法用二进制表达,返回NAN

因此最终返回[1,NAN,NAN]

Ending

看完这四道题目,是不是觉得有点意思呢?以上就是本人对前几天学习的部分总结了,感谢阅读。

相关推荐
云边有个稻草人1 小时前
智启未来:当知识库遇见莫奈的调色盘——API工作流重构企业服务美学
前端·数据库
仟濹6 小时前
【HTML】基础学习【数据分析全栈攻略:爬虫+处理+可视化+报告】
大数据·前端·爬虫·数据挖掘·数据分析·html
小小小小宇7 小时前
前端WebWorker笔记总结
前端
小小小小宇7 小时前
前端监控用户停留时长
前端
小小小小宇7 小时前
前端性能监控笔记
前端
烛阴8 小时前
Date-fns教程:现代JavaScript日期处理从入门到精通
前端·javascript
全栈小58 小时前
【前端】Vue3+elementui+ts,TypeScript Promise<string>转string错误解析,习惯性请出DeepSeek来解答
前端·elementui·typescript·vue3·同步异步
穗余8 小时前
NodeJS全栈开发面试题讲解——P6安全与鉴权
前端·sql·xss
独行soc9 小时前
2025年渗透测试面试题总结-匿名[校招]高级安全工程师(代码审计安全评估)(题目+回答)
linux·安全·web安全·面试·职场和发展·渗透测试
小蜜蜂嗡嗡9 小时前
flutter项目迁移空安全
javascript·安全·flutter