zhangxinxu/quiz

JS基础测试47期

Opened this issue · 15 comments

已知:

0.1 + 0.2 === 0.3;    // 返回值是false

请实现一个名为epsEqu的方法,可以实现浮点数相等:

epsEqu(0.1 + 0.2) === 0.3;    // 返回值是true

大家提交回答的时候,注意缩进距离,起始位置从左边缘开始;另外,github自带代码高亮,所以请使用下面示意的格式(1积分)。

```js
// 你的JS代码写在这里
 ```

本期小测会以要点形式进行回复。

/*
 * a: 输入浮点数;
 * b: 最多保留小数位,默认2;
*/
function epsEqu(a, b){ 
    b=b||2; 
    return parseFloat((a*Math.pow(10, b)).toFixed(0))/Math.pow(10, b);
}
function epsEqu(value, limit = 2) {
  return parseFloat(value.toFixed(limit))
}
zy017 commented
function epsEqu(n) {
    var s = String(n)
    // 小数点后连续多位(现在取8位以上)为0或9时就认为浮点数计算有误差,计算前面有几位正常数字,判断保留几位小数
    var reg = /(?<=\.)[0-9]*(?=0{8,}|9{8,})/
    var a = s.match(reg)
    if (a !== null) {
        var len = a[0].length
        return Number(n.toFixed(len))
    }
    return n
}

console.log('epsEqu(0.1 + 0.2) === 0.3', epsEqu(0.1 + 0.2) === 0.3)
console.log('epsEqu(0.1 + 0.7) === 0.8',epsEqu(0.1 + 0.7) === 0.8)
console.log('epsEqu(1.3 - 1) === 0.3', epsEqu(1.3 - 1) === 0.3)
console.log('epsEqu(0.3 - 0.2) === 0.1', epsEqu(0.3 - 0.2) === 0.1)
console.log('epsEqu(0.1 * 0.2) === 0.02', epsEqu(0.1 * 0.2) === 0.02)
console.log('epsEqu(0.8 * 3) === 2.4', epsEqu(0.8 * 3) === 2.4)
console.log('epsEqu(19.9 * 100) === 1990', epsEqu(19.9 * 100) === 1990)
console.log('epsEqu(0.3 / 0.1) === 3', epsEqu(0.3 / 0.1) === 3)
console.log('epsEqu(0.69 / 10) === 0.069', epsEqu(0.69 / 10) === 0.069)
const epsEqu = (val,num=2) => parseFloat(val.toFixed(num))
/**
 * 将浮点数保留16位小数处理
 * @param {number} num 浮点数
 */
function epsEqu (num) {
  return Number.parseFloat((num).toPrecision(16))
}

console.log(epsEqu(0.1 + 0.2) === 0.3) // true

可惜js不支持运算符重载,所以我认为还是要通过传参来知道保留几位小数

function epsEqu(n, decimals = 15) {
  return Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`)
}
/*举几个例子
0.07*10=0.7
1e5+1e-10=100000.0000000001
*/
console.log(epsEqu(0.1 + 0.2))
console.log(epsEqu(0.3 - 0.1))
console.log(epsEqu(0.3 - 0.01))
console.log(epsEqu(0.4321 - 0.01))
console.log(epsEqu(1))
console.log(epsEqu(11))
console.log(epsEqu(11.1))
console.log(epsEqu(11.000005))
function epsEqu(val) {
  //补充数据,我是希望像0.0~99这种能够进位为1.0~03格式
  var patch = Math.pow(0.1, 16)
  val += patch
  val += ''
  //将最后三位删除掉
  val = val.replace(/\d{3}$/, '')
  return Number(val)
}
function epsEqu(float) {
  return +(float).toFixed(16)
}
function epsEqu(a,b){
    return Math.abs(a - b) < Number.EPSILON
}

const a = 0.1 + 0.2
const b = 0.3
epsEqu(a,b)

心中目标答案:Math.abs(a - b) < Number.EPSILON

Number.toPrecision(16)也是一种方法。

心中目标答案:Math.abs(a - b) < Number.EPSILON

Number.toPrecision(16)也是一种方法。

经实践,Number.toPrecision(16)并不适合所有的情况,比如1 - 0.9就不行了;还是Math.abs(a - b) < Number.EPSILON比较保险 😂。

解题思路,是整数和整数,小数和小数单独相加。
然后用字符串拼起来。
不过我这边用的是函数式拿到需要相加的两个数字,而不是直接拿两个数字相加的结果去处理的。
不知道这个是否符合题意。

function epsEqu(n1) {
    return {
        add: function (n2) {
            const [k1, k2 = 0] = String(n1).split('.');
            const [i1, i2 = 0] = String(n2).split('.');
            const numF = parseInt(k2) + parseInt(i2);
            const numI = parseInt(k1) + parseInt(i1);
            return parseFloat(numI + parseInt(numF / 10) + '.' + numF % 10);
        }
    };
};
console.log(epsEqu(0.1).add(0.2) === 0.3);
const epsEqu = (a, b) => Math.abs(a - b) <  Number.EPSILON

 顺便说还有一个现象,当有如下代码的时候

Math.abs(1.1+1.3-2.4) <= Number.EPSILON // false

最终结果是 true ,所以使用 EPSILON 也是有误差的 ,对吗?

心中目标答案:Math.abs(a - b) < Number.EPSILON
Number.toPrecision(16)也是一种方法。

经实践,Number.toPrecision(16)并不适合所有的情况,比如1 - 0.9就不行了;还是Math.abs(a - b) < Number.EPSILON比较保险 。

好的,赞!

function epsEqu(a, b) {
  return Math.fround(a) === Math.fround(b)
}