国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

雙重按位非運(yùn)算符 ~~ 對(duì)數(shù)字取整

這篇具有很好參考價(jià)值的文章主要介紹了雙重按位非運(yùn)算符 ~~ 對(duì)數(shù)字取整。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

介紹

按位非運(yùn)算符(~)將操作數(shù)的位反轉(zhuǎn)。它將操作數(shù)轉(zhuǎn)化為 32 位的有符號(hào)整型。也就是可以對(duì)數(shù)字進(jìn)行取整操作(保留整數(shù)部分,舍棄小數(shù)部分)。

~-2 // 1
~-2.222 // 1

并且按位非運(yùn)算時(shí),任何數(shù)字?x(已被轉(zhuǎn)化為 32 位有符號(hào)整型)?的運(yùn)算結(jié)果都是?-(x + 1) 。

那么雙重按位非(~~)對(duì)數(shù)字的運(yùn)算結(jié)果就是?-(-(x + 1) + 1),結(jié)果就是 x 。

所以利用 ~~ 操作數(shù)字時(shí)就可對(duì)其進(jìn)行取整操作(右移操作符 x >> 0 和按位或操作符 x | 0 也有相同作用)。

如果操作的不是 Number 類型的,操作的對(duì)象會(huì)先轉(zhuǎn)化 Number 類型,下面一起來(lái)看看。

操作原始數(shù)據(jù)類型時(shí)

~~(-2.999);  // => -2
~~null; // => 0
~~undefined; // => 0
~~0;         // => 0
~~(1/0);     // => 0
~~false;     // => 0
~~true;      // => 1
~~'1234'     // => 1234
~~'1234asdf' // => 0
~~NaN        // => 0

~~ 對(duì)于不能轉(zhuǎn)化為數(shù)字的數(shù)據(jù)(NaN) ,操作的結(jié)果為 0

右移操作符 >> 和按位或操作符 | 也是如此。

(-2.999) >> 0   // => -2
null >> 0       // => 0
undefined >> 0  // => 0
0 >> 0          // => 0
(1/0) >> 0      // => 0
false >> 0      // => 0
true >> 0       // => 1
'1234' >> 0     // => 1234
'1234asdf' >> 0 // => 0
NaN >> 0        // => 0

(-2.999) | 0   // => -2
null | 0       // => 0
undefined | 0  // => 0
0 | 0          // => 0
(1/0) | 0      // => 0
false | 0      // => 0
true | 0       // => 1
'1234' | 0     // => 1234
'1234asdf' | 0 // => 0
NaN | 0        // => 0

操作對(duì)象數(shù)據(jù)類型時(shí)

當(dāng) ~~ 作用于對(duì)象類型時(shí),對(duì)象類型會(huì)先隱式轉(zhuǎn)化為數(shù)字,轉(zhuǎn)化的結(jié)果取決于對(duì)象的 valueOf 方法和 toString 方法返回的結(jié)果。如果對(duì)象類型轉(zhuǎn)化后最終的結(jié)果是 NaN,那么 ~~ 操作 NaN 則會(huì)直接返回 0。

詳細(xì)的轉(zhuǎn)換過(guò)程:

  1. 調(diào)用對(duì)象的valueOf方法
    如果該方法返回一個(gè)原始值,JavaScript會(huì)嘗試將這個(gè)原始值轉(zhuǎn)換為一個(gè)數(shù)字。如果valueOf方法返回的還是一個(gè)對(duì)象,JavaScript會(huì)繼續(xù)調(diào)用對(duì)象的toString方法。

  2. 調(diào)用對(duì)象的toString方法
    這個(gè)方法返回一個(gè)字符串,然后JavaScript會(huì)嘗試將這個(gè)字符串轉(zhuǎn)換為一個(gè)數(shù)字。

  3. 轉(zhuǎn)換字符串為數(shù)字
    一旦從valueOftoString方法中獲得了一個(gè)原始值(通常是字符串),JavaScript會(huì)按照字符串到數(shù)字的轉(zhuǎn)換規(guī)則來(lái)處理這個(gè)值。

如果valueOftoString返回的值是NaN,那么結(jié)果就是NaN。如果字符串不能被解析為一個(gè)有效的數(shù)字,結(jié)果也是NaN。 ~~ 操作 NaN 返回 0

所以也就有下面的結(jié)果:

~~{};    // => 0
~~{a:1}  // => 0
~~[];    // => 0
~~[1];   // => 1
~~[1,2]; // => 0

對(duì)于數(shù)組而言,將數(shù)組轉(zhuǎn)化為數(shù)字,會(huì)調(diào)用數(shù)組的 toString()。

數(shù)組的?toString?方法實(shí)際上在內(nèi)部調(diào)用了?join()?方法來(lái)拼接數(shù)組并返回一個(gè)包含所有數(shù)組元素的字符串,元素之間用逗號(hào)分隔。如果?join?方法不可用或者不是函數(shù),則會(huì)使用?Object.prototype.toString?來(lái)代替,并返回?[object Array]。

上面的 [1,2] 經(jīng)過(guò) toString() 后是 '1,2' , 轉(zhuǎn)為數(shù)字則是 NaN。所以 ~~[1,2] 結(jié)果為 0。

下面是對(duì)象有自定義的 valueOf() 或者 toString() 情況

var a = {
    valueOf:function(){return '11'},  // 字符串'11' 可被轉(zhuǎn)化為 數(shù)字 11
    toString:function(){return 12}
}
~~a // => 11

var b = {
    valueOf:function(){return 'asdf'}, // 字符串'asdf' 轉(zhuǎn)化為 NaN
    toString:function(){return 12}
}
~~b // => 0

var c = {
    toString:function(){return 12} // 沒(méi)有 valueOf() ,則調(diào)用 toString()
}
~~c // => 12

var d = {
    toString:function(){return 'asdf'} // 字符串'asdf' 轉(zhuǎn)化為 NaN
}
~~d // => 0

可進(jìn)行運(yùn)算的數(shù)字的有效范圍

由于 按位運(yùn)算總是將操作數(shù)轉(zhuǎn)換為 32 位整數(shù)。 超過(guò) 32 位的數(shù)字將丟棄其最高有效位。如下例子中(來(lái)自MDN),超過(guò) 32 位的整數(shù)將轉(zhuǎn)換為 32 位整數(shù):

Before: 11100110111110100000000000000110000000000001
After:              10100000000000000110000000000001

再比如 ~~ 操作日期類型數(shù)據(jù),DatevalueOf?方法返回以數(shù)值格式表示的一個(gè)?Date?對(duì)象的原始值,從 1970 年 1 月 1 日 0 時(shí) 0 分 0 秒到該日期對(duì)象所代表時(shí)間的毫秒數(shù)。

返回的毫秒數(shù)是超過(guò) 32 位的整數(shù),不在 ~~ 操作的有效范圍內(nèi),結(jié)果就不會(huì)是期望的那樣。

var date = new Date()
Number(date) // 1706671595364
~~date // 1569578852  結(jié)果失真

所以只有對(duì) 32位浮點(diǎn)數(shù)(經(jīng)測(cè)試,有效范圍為:[-2^31,2^31-1],即[-2147483648,2147483647]) 進(jìn)行按位運(yùn)算時(shí)才會(huì)得到期望的結(jié)果。

~~2147483647.1 // => 2147483647  正確
~~2147483648.1 // => -2147483648  不正確

~~-2147483648.1 // => -2147483648  正確
~~-2147483649.1 // => 2147483647 不正確

需要注意的是,如果整數(shù)部分和小數(shù)部分?jǐn)?shù)字之和超過(guò)了 16 位(不包括小數(shù)點(diǎn)),那么雙重按位非操作符的結(jié)果也會(huì)不正確:( Number編碼的精度 的算術(shù)會(huì)受到舍入的影響。)

雙重按位非運(yùn)算符 ~~ 對(duì)數(shù)字取整

雙重按位非運(yùn)算符 ~~ 對(duì)數(shù)字取整

使用場(chǎng)景

對(duì)一些函數(shù)入?yún)⑿r?yàn)及處理方面有用,比如傳入的可能是任意數(shù)字,需要排除掉極端情況(NaNInfinity),然后取整;

function fn(){
    var param = arguments[1]
    if(param === 'number' && !isNaN(foo) && foo !== Infinity){
        var value = Number(param) || 0;
        value = (value < 0)
             ? Math.ceil(value)
             : Math.floor(value);
    }
}

使用 ~~ 后:

function fn(){
    var value = ~~arguments[1]
}

拓展

左移(<<)和右移(>>)運(yùn)算符可以用來(lái)進(jìn)行快速的二進(jìn)制乘法和除法操作。左移一個(gè)數(shù)值實(shí)際上等于將這個(gè)數(shù)值乘以2的某個(gè)冪,而右移一個(gè)數(shù)值則等于將這個(gè)數(shù)值除以2的某個(gè)冪(忽略余數(shù))。

但這個(gè)使用場(chǎng)景只適用對(duì) 2 的乘法除法操作(。。。)

let result = 6 * 2; // 結(jié)果是12

let base = 6; // 二進(jìn)制表示為 110 
let shift = 1; // 左移1位 
let result = base << shift; // 結(jié)果是12,二進(jìn)制表示為 1100
let result = 12 / 2; // 結(jié)果是6,但可能得到一個(gè)浮點(diǎn)數(shù) let roundedResult = Math.floor(12 / 2); // 結(jié)果是6,確保得到整數(shù)

let base = 12; // 二進(jìn)制表示為 1100 
let shift = 1; // 右移1位 
let result = base >> shift; // 結(jié)果是6,二進(jìn)制表示為 110

總結(jié)

本文探討了使用雙重按位非運(yùn)算符 ~~ 對(duì)操作數(shù)取整的原理。

  • ~~ 之所以可以用來(lái)取整,是因?yàn)榘次贿\(yùn)算操作數(shù)轉(zhuǎn)化為 32 位的有符號(hào)整型,會(huì)舍棄掉小數(shù)部分。并且按位非運(yùn)算(~)時(shí),任何數(shù)字?x(已被轉(zhuǎn)化為 32 位有符號(hào)整型)?的運(yùn)算結(jié)果都是?-(x + 1)?。那么雙重按位非(~~)對(duì)數(shù)字的運(yùn)算結(jié)果就是?-(-(x + 1) + 1),結(jié)果就是?x?。
  • 操作數(shù)是數(shù)字并且在位運(yùn)算的有效范圍內(nèi)([-2^31,2^31-1]),~~ 取整才會(huì)得到期望的結(jié)果。
  • 使用場(chǎng)景方面對(duì)一些函數(shù)入?yún)⑿r?yàn)及處理方面可能有用

折騰完畢 ??。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-825089.html

到了這里,關(guān)于雙重按位非運(yùn)算符 ~~ 對(duì)數(shù)字取整的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包