电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

JAVA位運算的知識點總結

瀏覽:5日期:2022-09-04 17:51:46

一、在計算機中數據是如何進行計算的?

1.1:java中的byte型數據取值范圍

我們最開始學習java的時候知道,byte類型的數據占了8個bit位,每個位上或0或1,左邊第一位表示符號位,符號位如果為1表示負數,為0則表示正數,因此要推算byte的取值范圍,只需要讓數值位每一位上都等于1即可。

我們來用我們的常規思維來分析下byte類型的取值范圍:

JAVA位運算的知識點總結

圖1

如果按照這種思路來推算,七個1的二進制數轉換為十進制是127,算上符號位,取值范圍應為:-127~+127,但事實上我們知道,byte的取值范圍是-128~127,這里先打個問號,接著往下看。

現在讓我們計算下byte類型的7加上byte類型的-2是多少:

JAVA位運算的知識點總結

圖2

誒?跟我們預想的不一樣,因為我們是知道7和-2的和應該是5才對,結果應該表示為:00000101,但事實上通過圖2的結果來看確實跟預想的不一樣,所以計算機在做計算的時候,肯定不是表面上的符號位+數值位的方式進行的計算的。

1.2:原碼,反碼,補碼

我們先來看下定義:

👉 原碼定義:符號位加后面的數值,比如圖2里的00000111和10000010都是原碼,原碼比較簡單,就是我們在上面單純理解上的原值。

👉 反碼定義:正數的反碼就是它的原碼,負數的反碼符號位不變,其余數值位全部按位取反,例如:

00000111的反碼:00000111

10000010的反碼:11111101

👉 補碼定義:同樣的,正數的補碼仍然等于它的原碼本身,負數的補碼等于它自己的反碼+1,例如:

00000111的補碼:00000111

10000010的補碼:11111110

🌴 總結:正數的原碼、反碼、補碼完全一致,負數的反碼等于它原碼的數值位按位取反,負數的補碼等于它的反碼+1

現在讓我們用反碼的方式來計算下圖2中的式子:

JAVA位運算的知識點總結

圖3

利用數值的反碼計算出的結果已經很接近正確答案了,+4的反碼等于它的原碼,現在只需要讓它+1就是正確答案,還記得補碼的定義嗎?負數的補碼等于它的反碼+1,那現在讓我們用補碼做下計算試試?

JAVA位運算的知識點總結

圖4

ok,我們發現,用它們的補碼做加法,得到的數值就是我們想要的正確答案,事實上,計算機并沒有減法運算器,所有的減法運算,都是以一個正數加上一個負數的形式來交給加法運算器計算的,由于負數的符號位為1,雖然我們人是知道它的含義,但是作為計算機,它是不知道第一位是符號位的,它要做的就僅僅是讓兩個數相加而已,正是因為如此,我們才不能簡簡單單保存負數,通過圖4我們知道,兩個數的補碼相加,可以得到一個準確的數值。

再舉個相加結果為負數的例子,讓兩個負數相加:

JAVA位運算的知識點總結

圖5

如果結果為負數的話,也是適用的,只是它仍然是以補碼的形式存放的,需要轉成原碼才符合我們人的理解方式。

現在回到上面留下的問題,為什么byte的取值范圍是-128~127呢?

我們之前按照圖1里的理解,理所應當的以為它應該是-127~127的范圍,那是因為我們按照圖1的理解方式,數值就是以符號位+數值位的方式理解的(也就是按照原碼的方式理解的),但是你可以想一下,如果按照圖1那種理解方式,是不是會存在兩個0值呢?

即:10000000和00000000,+0和-0;

其次如果站在機器角度上來說,所有的負數都很大,至少要比所有正數大,因為負數的最高位也就是符號位都是1,顯然這是不對的,通過本節我們知道了,所有的數均通過自己的補碼完成計算,如果將最后得到的結果轉成原碼,就是我們人眼可以理解的最終值(符號位+數值位),如果現在利用補碼的方式做理解,符號位為0的數沒啥好說的,自然取值區間為:0~127,但是符號位為1的負數呢?負數就存在一個特殊值(也就是我們之前片面理解的-0):10000000,如果按照原碼理解它是-0,但我們前面說過,計算機里所有數字,都是以補碼的方式參與運算的,而負數的補碼不等于其原碼,這個10000000在計算機里顯然是某個負數的補碼,那么問題就變的簡單多了,即10000000是誰的補碼呢?答案是:-128,這也是為什么負數的取值范圍會比正數多一個的原因,byte類型如此,其它類型也是如此,比如int型的負數取值也比正數多1。

這一塊的定義要清晰,對理解后面的位運算會有很大的幫助。

二、java中的位運算 2.1:與運算

與運算符號:&

與運算特點:1&1=1、1&0=0、0&1=0、0&0=0

現在我們來舉一個例子:

JAVA位運算的知識點總結

圖6

讓我們再來試試負數:

JAVA位運算的知識點總結

圖7

2.2:或、異或

跟與運算的運算方式一致,只不過規則不太一樣:

或運算符號:|

或運算規則:1|1=1、1|0=1、0|1=1、0|0=0

異或運算符號:^

異或運算規則:1^1=0、1^0=1、0^1=1、0^0=0

2.3:按位取反

取反符號:~

即一個數對自己取反,例如:

某個數字a的二進制為: 1010110

則~a為: 0101001

2.4:左移運算

左移運算符:<<

例如:

JAVA位運算的知識點總結

圖8

位運算越界&數位拋棄:

圖8中的116的二進制數的數值位為7位,符號位為0,此時如果左移超過24位,就會出現負數,為什么會這樣?因為java中的位移越界時,java會拋棄高位越界部分,我們知道java里int類型的第一位是符號位,如果符號位是1,則表示其為負數,現在將數值位占7bit符號位為0的116左移24位,就會出現下方結果:

01110100000000000000000000000000

正好31位占全,頂至符號位,低位補0,我們稱24為116的不越界的最大左移值,若超出這個值,就會越界,比如左移25位:

11101000000000000000000000000000

顯然左移25位后會把數值位的1移動到符號位,這時它表示為一個負數的補碼。根據這個規則,我們如果讓其左移28位,則值為:

01000000000000000000000000000000

也就是十進制的1073741824,即:116 << 28 = 1073741824,那如果越界過多呢?比如int型的數據,左移32位:116 << 32 = 116

會發現,如果左移自己位數一樣多的位數,那么這個數就等于它本身,因此運算符合以下規則:

設x為被位移值,y為本次位移的位數,z為x所屬類型的最大存儲位數:

x << y = x << (y%z)

如果是int型(32位,long型就用64代入計算),符合如下規則:

116 << 4 = 116 << (4%32) = 116 << 4 = 1856

116 << 32 = 116 << (32%32) = 116 << 0 = 116

116 << 36 = 116 << (36%32) = 116 << 4 = 1856

2.5:有符號右移運算&無符號右移運算

有符號右移運算符:>>

無符號右移運算符:>>>

例如:a >> b表示a右移b位,跟上面的左移例子一樣,右移也會有越界問題,只是右移越界是從右邊開始拋棄越界部分的,右移操作有符號位干擾,如果是正數右移,無此干擾項,因為符號位本就是0右移不會影響值的準確性,但如果是負數,第一位是符號位,且值為1,右移就有影響了,現在仍然以116為例:

正數右移:

JAVA位運算的知識點總結

圖9

上述是正數,右移無影響,但是負數,這里以-116為例,我們知道負數在計算機里是以補碼的形式存儲的,所以圖里直接用-116的補碼做運算,位移過程如下:

JAVA位運算的知識點總結

圖10

你會發現右移跟左移不一樣,左移是不用擔心自己符號位存在“補位”問題的,但是右移存在,如圖中-116右移4位后,左邊第一位,也就是符號位,就面臨著問題,那我現在是該補1呢,還是補0呢?這也就是為什么右移操作會存在有符號右移和無符號右移兩種移動方式:

☘️ 有符號右移:依照原符號位,如果原符號位是1,那么圖4里需要空位全部補1,如果原符號位為0,則全部補0

☘️ 無符號右移:無視原符號位,全部補0

現在讓我們用有符號的方式將-116右移4位,即-116 >> 4,按照有符號的規則,補位符合原符號位,則右邊4位全部補1:

JAVA位運算的知識點總結

圖11

得到的仍然是個負數,它仍然是一個補碼,圖里展示不開,它的結果為:11111111111111111111111111111000,經轉換可知它是-8的補碼,即:-116 >> 4 = -8

現在再試試用無符號右移,根據無符號的特點,右移后的前四位無腦補0:

JAVA位運算的知識點總結

圖12

圖里展示不開,它的結果為:00001111111111111111111111111000

可見它是個正數,轉換成十進制為:268435448,即:-116 >>> 4 = 268435448

最后說一下,跟左移一樣,右移里不管是有符號還是無符號,也符合取余的方式,計算出位移的最終位數:

-116 >> 4 = -116 >> (4%32) = -116 >> 4 = -8

-116 >> 32 = -116 >> (32%32) = -116 >> 0 = -116

-116 >> 36 = -116 >> (36%32) = -116 >> 4 = -8

2.6:類型轉換溢出

了解完位運算,來看一個比較實際的問題,看下面的代碼:

long a = 8934567890233345621L;int b = (int) a; //b的值為-1493678507

最終b的值是一個負數,這是由于long型64位,讓int型強行接收,會出現位溢出的問題,這個流程如下:

JAVA位運算的知識點總結

圖13

三、位運算在實際項目中的運用

位運算的性能是非常好的,相比運算流程,計算機更喜歡這種純粹的邏輯門和移動位置的運算,但位運算在平常的業務代碼里并不太常見,因為它的可讀性不太好,但是我們仍然可以利用位運算來解決一些實際項目里的問題。

比如用來表示開關的功能,比如需求里經常有這種字段:是否允許xx(0不允許,1允許),是否有yy權限(0沒有,1有),是否存在zz(0不存在,1存在)

上面只是舉例,類似這種只有兩種取值狀態的屬性,如果當成數據庫字段放進去的話,太過浪費,如果之后又有類似的字段,又得新增數據庫字段,為了只有兩種取值的字段,實在是不太值得。

這個時候何不用一個字段來表示這些字段呢?你可能已經猜到要怎么做了:

JAVA位運算的知識點總結

圖14

頂一個int型或者long型的字段,讓它的每一個二進制位擁有特殊含義即可,然后按照位運算將其對應的位置上的數值變成0或1,那如何將某個數的二進制位第x位上的數值變成1或0呢?其實這在位圖結構里經常用到,就是利用1這個特殊的值作位移運算后再與原值進行位運算,讓我們看下這個過程:

把一個數的第2位的字符變成1,現在假設這個數初始化為0,int型,我們把它當成二進制展示出來:

JAVA位運算的知識點總結

圖15

現在如何把這個數的第二位變成1呢?目前是這樣做的:

0 | 1 << 1

即原值跟1左移1位后的值作或運算,先來看看1 << 1的結果:

JAVA位運算的知識點總結

圖16

然后拿著圖16的結果,跟原數(也就是0)進行或運算:

JAVA位運算的知識點總結

圖17

可以看到,原數的第二位已經被置為1了,它的十進制對應2,其它位的數置為1也大同小異,例如,現在讓第6位也變成1只需要:

2 | 1 << 5

即拿著原值(現在為2)跟1左移5位后的數做或運算,這個流程如下:

JAVA位運算的知識點總結

圖18

看完了把某個位置的數值置為1,那如何把某位設置為0呢?我們現在把圖18里的結果的第6位重新置回0,目前的做法為:

34 & ~(1 << 5)

即拿著原值(經過上面幾步的運算,現在值為32)跟1左移5位按位取反后的數做與運算,來看下這個流程:

JAVA位運算的知識點總結

圖19

經過上面的流程,就可以把原值的第6位變成0了。

那么我們知道了讓一個數的二進制位的某位變成0或1的方法,那如何知道一個數的某位上究竟是0還是1呢?畢竟我們業務代碼需要知道第幾位代表什么意思并且獲取到對應位置上的值。

假如我現在想知道十進制int型數34的第6位是0還是1,寫法如下:

34 >> 5 & 1

即讓原值(34)右移5位后跟1做與運算,來看下這個流程:

JAVA位運算的知識點總結

圖20

由圖可以看出,想要知道一個數的第幾位是1還是0,只需要將其對應位置上的值“逼”到最后一位,然后跟1相與即可,如果對應位置上的值是0,那么與1相與后的結果一定為0,反之一定為1.

☘️ 總結

到這里已經說完了為什么要用一個數表示那么多開關,以及如何給一個開關位設置對應的開關值,以及如何找到對應開關位的值,有了這些操作,我們再也不需要為這種只有0和1取值的字段新增數據庫字段了,因為一個int型的數字,就可以表達32個開關屬性,如果超了,還可以擴成64位的long型~

到此這篇關于JAVA位運算的知識點總結的文章就介紹到這了,更多相關JAVA有關位運算的全套梳理內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Java
相關文章:
主站蜘蛛池模板: 上海乾拓贸易有限公司-日本SMC电磁阀_德国FESTO电磁阀_德国FESTO气缸 | 螺旋压榨机-刮泥机-潜水搅拌机-电动泥斗-潜水推流器-南京格林兰环保设备有限公司 | 华禹护栏|锌钢护栏_阳台护栏_护栏厂家-华禹专注阳台护栏、楼梯栏杆、百叶窗、空调架、基坑护栏、道路护栏等锌钢护栏产品的生产销售。 | 旋转滴界面张力仪(张力测定仪器)-百科| 飞歌臭氧发生器厂家_水处理臭氧发生器_十大臭氧消毒机品牌 | 丽陂特官网_手机信号屏蔽器_Wifi信号干扰器厂家_学校考场工厂会议室屏蔽仪 | 特种阀门-调节阀门-高温熔盐阀-镍合金截止阀-钛阀门-高温阀门-高性能蝶阀-蒙乃尔合金阀门-福建捷斯特阀门制造有限公司 | 紫外线老化试验箱_uv紫外线老化试验箱价格|型号|厂家-正航仪器设备 | 精准猎取科技资讯,高效阅读科技新闻_科技猎 | 便携式表面粗糙度仪-彩屏硬度计-分体式粗糙度仪-北京凯达科仪科技有限公司 | vr安全体验馆|交通安全|工地安全|禁毒|消防|安全教育体验馆|安全体验教室-贝森德(深圳)科技 | 动物解剖台-成蚊接触筒-标本工具箱-负压实验台-北京哲成科技有限公司 | 钢衬四氟管道_钢衬四氟直管_聚四氟乙烯衬里管件_聚四氟乙烯衬里管道-沧州汇霖管道科技有限公司 | 承插管件_不锈钢承插管件_锻钢高压管件-温州科正阀门管件有限公司 | 光谱仪_积分球_分布光度计_灯具检测生产厂家_杭州松朗光电【官网】 | 12cr1mov无缝钢管切割-15crmog无缝钢管切割-40cr无缝钢管切割-42crmo无缝钢管切割-Q345B无缝钢管切割-45#无缝钢管切割 - 聊城宽达钢管有限公司 | 恒温水槽与水浴锅-上海熙浩实业有限公司| 网带通过式抛丸机,,网带式打砂机,吊钩式,抛丸机,中山抛丸机生产厂家,江门抛丸机,佛山吊钩式,东莞抛丸机,中山市泰达自动化设备有限公司 | EPDM密封胶条-EPDM密封垫片-EPDM生产厂家 | 中国产业发展研究网 - 提供行业研究报告 可行性研究报告 投资咨询 市场调研服务 | 干式磁选机_湿式磁选机_粉体除铁器-潍坊国铭矿山设备有限公司 | 书法培训-高考书法艺考培训班-山东艺霖书法培训凭实力挺进央美 | 玻璃钢型材-玻璃钢风管-玻璃钢管道,生产厂家-[江苏欧升玻璃钢制造有限公司] | 东亚液氮罐-液氮生物容器-乐山市东亚机电工贸有限公司 | 工业设计,人工智能,体验式3D展示的智能技术交流服务平台-纳金网 J.S.Bach 圣巴赫_高端背景音乐系统_官网 | 智能型高压核相仪-自动开口闪点测试仪-QJ41A电雷管测试仪|上海妙定 | 注塑_注塑加工_注塑模具_塑胶模具_注塑加工厂家_深圳环科 | 河南膏药贴牌-膏药代加工-膏药oem厂家-洛阳今世康医药科技有限公司 | 防水套管厂家_刚性防水套管_柔性防水套管_不锈钢防水套管-郑州中泰管道 | arch电源_SINPRO_开关电源_模块电源_医疗电源-东佑源 | 废气处理设备-工业除尘器-RTO-RCO-蓄热式焚烧炉厂家-江苏天达环保设备有限公司 | 石家庄救护车出租_重症转院_跨省跨境医疗转送_活动赛事医疗保障_康复出院_放弃治疗_腾康26年医疗护送转诊团队 | 加气混凝土砌块设备,轻质砖设备,蒸养砖设备,新型墙体设备-河南省杜甫机械制造有限公司 | 通风气楼_通风天窗_屋顶风机-山东美创通风设备有限公司 | 成都茶楼装修公司 - 会所设计/KTV装修 - 成都朗煜装饰公司 | 全自动包装秤_全自动上袋机_全自动套袋机_高位码垛机_全自动包装码垛系统生产线-三维汉界机器(山东)股份有限公司 | 光泽度计_测量显微镜_苏州压力仪_苏州扭力板手维修-苏州日升精密仪器有限公司 | 超细粉碎机|超微气流磨|气流分级机|粉体改性设备|超微粉碎设备-山东埃尔派粉碎机厂家 | 西安展台设计搭建_西安活动策划公司_西安会议会场布置_西安展厅设计西安旭阳展览展示 | 据信,上课带着跳 D 体验-别样的课堂刺激感受引发网友热议 | 深圳美安可自动化设备有限公司,喷码机,定制喷码机,二维码喷码机,深圳喷码机,纸箱喷码机,东莞喷码机 UV喷码机,日期喷码机,鸡蛋喷码机,管芯喷码机,管内壁喷码机,喷码机厂家 |