[20210503]LeetCode每日一题 - 7. 整数反转

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。

如果反转后整数超过 32 位的有符号整数的范围 [−2^31,  2^31 − 1] ,就返回 0。

假设环境不允许存储 64 位整数(有符号或无符号)。

地址:7.整数反转

对于使用ts来说,这个非常方便:

function reverse(x: number): number {
    const result = Number(Math.abs(x).toString().split('').reverse().join('')) * (x < 0 ? -1 : 1);

    if (result > 2 ** 31 - 1 || result < 2 ** 31 * -1) return 0;

    return result;
};

AC,执行用时 108 ms,击败55%的ts提交者

 

然而,我在看88ms解答时间时,发现他的方法:

function reverse(x: number): number {
    let flag:number = (x>0)?1:-1
    x = Math.abs(x)
    let res:number = 0

    while(x) {
        res = res*10 + x%10
        x = ~~(x/10)
        if((res > (Math.pow(2,31) - 1)) || (res<Math.pow(-2,31))) {
            return 0
        }
    }
    
    return res * flag
};

然而我即使使用这个方法去提交,最快也就124ms


他的解答方法中,有一个操作符:~~,并不常用,对此我查了一下资料:

  1. ~~主要是用来取整,或字符串数字转纯数字的方法,例如 '123' => 123, 123.2 => 123, '123.2' => 123
  2. 如果字符串中有非数字字符,一律返回0,例如 '12a' => 0, 'abc' => 0
  3. 对于boolean类型,true返回1,false返回0
  4. 特殊类型,例如undefined类型等,先转化为boolean,再根据第三条规则返回

原博客地址:地址

这篇博客下有个回复,提到了Math.trunc()方法,为此查了一下MDN:地址

这两个方法的相同点在于:

  1. 都会将小数取整,或字符串数字转纯数字,与上方~~操作符的第一条处理结果一致
  2. 对于boolean类型,true返回1,false返回0
  3. 对于null,返回0

不同点在于:

  1. 如果Math.trunc()中传入任何非数字的字符,直接返回NaN
  2. 如果是特殊类型,例如undefined,返回NaN
  3. 如果是'-0',或-0,Math.trunc()返回的是有符号的-0,而不是无符号的0,~~则全部返回无符号的0

据此可见:

  1. Math.trunc()这个方法先使用Number处理数据,如果是NaN数据,直接返回,非NaN,再取整处理
  2. Math.trunc()保留了-0的符号,这个对一般人看来是没什么用的,其实-0和0并不完全相同,有坑!

在js中,无论严格模式与否,-0 === 0,但 1 / -0 !== 1 / 0

1 / -0 => -Infinity

1 / 0 => Infinity

-Infinity !== Infinity

根据 javascript 64位双精度浮点数,第 1 位是正负数符号位(sign),0代表正数,1代表负数,中间的 11 位存储指数(exponent),用来表示次方数,最后的 52 位是尾数(mantissa),超出的部分自动进一舍零。所以正负0的表示是不同的。

但为什么 -0 === 0呢?

JS对于if判断的规范如下:

比较 x === y,x 和 y 为值,需要产出 true 或 false。

比较过程如下:

  • 如果 Type(x) 与 Type(y) 的结果不一致,返回 false。
  • 如果 Type(x) 结果为 Undefined,返回 true。
  • 如果 Type(x) 结果为 Null,返回 true。
  • 如果 Type(x) 结果为 Number,则
    • 如果 x 为 NaN,返回 false。
    • 如果 y 为 NaN,返回 false。
    • 如果 x 与 y 为同一个数字,返回 true。
    • 如果 x 为 +0,y 为 -0,返回 true。
    • 如果 x 为 -0,y 为 +0,返回 true。
    • 返回 false。
  • 如果 Type(x) 结果为 String,如果 x 与 y 为完全相同的字符序列(相同的长度和相同的字符对应相同的位置),返回 true,否则,返回 false。
  • 如果 Type(x) 结果为 Boolean,如果 x 与 y 都为 true 或 false,则返回 true,否则,返回 false。
  • 如果 x 和 y 引用到同一个 Object 对象,返回 true,否则,返回 false。

全等运算符虽然没有作类型转换,但也是针对 NaN+0-0 作了特殊处理。

(以上参考:地址

于此,如何判断 0 和 -0:

请使用 Object.is 方法,es6中的新方法:

Object.is(num, -0)

而Object.is返回一个boolean类型,告知比较值是否相同,其判断规范如下:

  • 都是 undefined
  • 都是 null
  • 都是 true 或 false
  • 都是相同长度的字符串且相同字符按相同顺序排列
  • 都是相同对象(意味着每个对象有同一个引用)
  • 都是数字且
    • 都是 +0
    • 都是 -0
    • 都是 NaN
    • 或都是非零而且非 NaN 且为同一个值

其对于-0和+0有了严格的判断,官方有了如下注解:

== 运算不同。  == 运算符在判断相等前对两边的变量(如果它们不是同一类型) 进行强制转换 (这种行为的结果会将 "" == false 判断为 true), 而 Object.is不会强制转换两边的值。

=== 运算也不相同。 === 运算符 (也包括 == 运算符) 将数字 -0 和 +0 视为相等 ,而将Number.NaN 与NaN视为不相等.

MDN Object.is:地址

 

综上所述:

  1. 对于非常用的操作符,慎用;
  2. 在IDE中(我用webStrom),==运算是会被warn的,原因就是上方官方注解,因此请直接使用===;
  3. 但===也不完美,原因也是官方注释: -0===+0, Number.NaN !== NaN,具体场景下还是根据需要去使用不同方法吧;
  4. 像在举例 1 / 0 和 1 / -0 时,对于分母还是要做好数字判断,否则出现这样的数据时,会有bug。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值