前言
今天总结一下前几天所学到的个四个考题,快来看看你能不能全部答对吧!
字符串相加
有人会说数字求和不是很简单吗,加法谁不会算呢?
虽然说加法算数确实不能,但是如果数字是一个非常非常大,简单的加法就无法得到正确的结果了。我们需要采用特殊的方法计算正确的结果。
当数字非常大的时候,如果使用普通的加法,是无法得到正确结果的,超出了计算范围。所以,这时候就需要我们把数字转成字符串,然后从末尾进行相加。这种题目是高精度的板子题也不算太难,只需要把加法过程用代码表示出来,就能解出来。
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
看完这四道题目,是不是觉得有点意思呢?以上就是本人对前几天学习的部分总结了,感谢阅读。