Java如何只使用位運算實現加減乘除

分享一波:程序員賺外快-必看的巔峰干貨

前言

接前面一篇博客,這又是某個公司的奇葩面試題(都說了到底是哪家公司才會出這種沒營養的面試題)。不過吐槽歸吐槽,這個題目還是有點學問的,比前面那個 不使用比較運算符如何比較兩個數的大小 強多了(但是還是能看出面試官是在存心刁難人)。

原題是“只給加法,如何實現減乘除”,我尋思著,既然減乘除都不給了,那就加大點難度,加法也別給了吧,今天就手動去實現加減乘除。這里只實現int類型的加減乘除。

一說到這種“不給xxx如何實現xxx的問題”,那第一個想到的就是位運算,因此本篇博客的各種運算也是基于位運算的。關于位運算的知識點,請閱讀本博客的看官們自行百度學習。。。。
加法

我們先舉個加法的例子:8+9=17,可以轉換成10+7,即:二者相加不考慮進位的值,和二者相加只考慮進位的值相加。我們再通過二進制來直觀的看一下。

0000 1000 (8)
0000 1001 (9)
0001 0001 (17)

[點擊并拖拽以移動]

下面描述一下思路(可能有點繞)。

首先我們看,直接二進制相加的結果,0+0=0,1+0=1,1+1=10。好像能看出點什么。前兩個的運算規則復合“異或運算”,而后者則復合與運算并左移1位。

到現在思路就清楚了:a^b的結果是不考慮進位的結果,而a&b<<1是只考慮進位的結果。把二者相加即可。如果相加后,可能還存在進位,那就讓這兩個數字繼續相加,一直到進位為0為止。這里使用遞歸去實現,感興趣的可以用循環實現,性能比遞歸要高。

public int add(int a, int b) {// 得到原位和int xor = a ^ b;// 得到進位和int forWoad = (a & b) << 1;return forWoad == 0 ? xor : add(xor, forWoad);
}

到這里,加法就實現完畢了
負數

計算機中的負數實現,是將正數按位取反獲取反碼,之后+1獲得補碼,這個結果就是某個正數所對應的負數。(這個在計算機組成原理、操作系統、計算機導論、離散數學等課本中都有,不記得的請翻一下大學課本。)。

負數的實現其實還是比較簡單的,按位取反之后+1即可。

public int negative(int num) {return add(~num, 1);
}

減法

實現了負數之后,我們第一步實現的加法就可以和負數進行運算了,而減法也就變得簡單起來。

減法的實現如4-2等價于4+(-2),我們直接使用加法和負數就可以實現。

public int minus(int a, int b) {return add(a, negative(b));
}

絕對值

接下來要實現乘法和除法。乘法和除法可能會有正數和負數相互計算的情況,因此我們實現乘除之前,需要先實現絕對值計算的功能,將運算數字轉換成絕對值進行乘除,之后判斷是否需要加上負號即可。

public int abs(int num) {if (num < 0) {num = minus(0, num);}return num;
}

乘法

乘法的實現,如11*10,乘法的流程如下面所示。

0000 1011 (11)
0000 1010 (10)

0001 0110 (1011<<1,相當于乘以0010)
0101 1000 (1011<<3,相當于乘以1000)

可以看到,二進制乘法的原理是:從乘數的低位到高位,遇到1并且這個1在乘數的右邊起第i(i從0開始)位,那么就把被乘數左移i位得到temp_i,直到乘數中的1遍歷完畢后,把根據各位1而得到的被乘數的左移值全部相加即得到乘法結果。

而至于存在負數的運算,可以先獲取負數的個數,再將兩個數字轉換成絕對值計算,最后判斷當負數是1個時,計算結果就是負數,其他情況則是正數。

public int multi(int a, int b) {// 先獲取負數的個數int negativeCount = negativeCount(a, b);// 負數轉正數進行計算a = abs(a);b = abs(b);int i = 0;int res = 0;// 乘數為0則結束while (b != 0) {// 處理乘數當前位if ((b & 1) == 1) {res = add(res, a << i);}b = b >> 1;i = add(i, 1);}if (negativeCount == 1) {// 轉為負數res = negative(res);}return res;
}

negativeCount方法

public int negativeCount(int a, int b) {int count = 0;if (a < 0) {count = add(count, 1);}if (b < 0) {count = add(count, 1);}return count;
}

乘法事實上有個簡單的實現。乘法就是個連加的過程,如5*4就是4個5相加,這個雖然性能比較低,但是操作起來簡單,感興趣的朋友可以自己去實現。
除法

除法沒有什么簡單的二進制實現方案,實際計算機中的除法也是通過連減去計算的。a/b的意義就是求a可以由多少個b組成,因此除法可以求a能減去多少個b。至于負數的情況,和乘法相同,不再介紹。

public int sub(int a, int b) {// 先獲取負數的個數int negativeCount = negativeCount(a, b);// 負數轉正數進行計算a = abs(a);b = abs(b);int res;if (a < b) {return 0;} else {res = add(sub(minus(a, b), b), 1);}if (negativeCount == 1) {// 轉為負數res = negative(res);}return res;
}

取模

取模運算的思路和除法一樣,也是個連減的過程,一直減到我們減不了為止,剩下的值就是我們要的結果。

public int mode(int a, int b) {// 先獲取負數的個數int negativeCount = negativeCount(a, b);// 負數轉正數進行計算a = abs(a);b = abs(b);int res;if (a < b) {res = a;} else {res = sub(minus(a, b), b);}if (negativeCount == 1) {// 轉為負數res = negative(res);}return res;
}

結語

總的來說,加減乘除的實現還是比較簡單的,只是對于初學者來說比較難想。熟悉了這類“不給xxx如何實現xxx”的題目之后,就能第一時間想到位運算了,通過位運算去實現運算符規則,實現起來就沒有什么難度了。

最后還是需要點評一下這道題。這個問題相比上次的問題,稍微的有那么點水平,但是還是不難看出面試官在刁難人。程序員需要懂的原理,應該是開發中的各種框架原理,如HashMap、Spring、Mybatis等,理解了原理才能更好的優化、擴展,以便于提高性能。而所謂的加減乘除原理并沒有這些重要,往往在上大學的時候也就了解過了。加減乘除原理的理解對性能優化幫助并不大,即使位運算性能比減法和除法高,但是這點性能損耗,在我們服務器動輒4g8g的情況下是沒有任何區別的。所以說面試的時候別問這種刁難人的問題啊,你就是造造火箭問問Spring也好!
*************************************優雅的分割線 **********************************

分享一波:程序員賺外快-必看的巔峰干貨

如果以上內容對你覺得有用,并想獲取更多的賺錢方式和免費的技術教程

請關注微信公眾號:HB荷包
在這里插入圖片描述
一個能讓你學習技術和賺錢方法的公眾號,持續更新

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:
http://www.pswp.cn/news/536996.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/536996.shtml
英文地址,請注明出處:http://en.pswp.cn/news/536996.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Netweaver里某個software component和C4C的版本

有同事問如何通過代碼的方式獲得Netweaver里某個Software component的版本信息&#xff0c;以及Cloud for Customer&#xff08;C4C&#xff09;的版本信息。 Netweaver 點了Detail按鈕后&#xff1a; 這些版本信息存在表CVERS里&#xff1a; C4C C4C的版本號在Help->About …

pmc訂單表格_復工了,讀一則“如何提升訂單準交率和生產效率”的真實故事

故事發生在中國南方小鎮上一個做辦公家具的公司……家具公司創建于1995年&#xff0c;是一家集研發、生產、銷售、服務為一體的現代辦公家具、酒店家具制造企業。主要產品有實木班臺系列、會議臺系列、職員桌系列、屏風系列、沙發系列、辦公座椅、酒店家具系列。在省外還有兩個…

GET和POST請求到底有什么區別?

分享一波:程序員賺外快-必看的巔峰干貨 看到這個標題&#xff0c;想必大部分人都已經想關掉這篇博客了。先別急&#xff0c;你真的知道這兩個的區別嗎&#xff1f; 做過WEB開發的朋友可能很熟悉&#xff0c;看到這個問題能立馬脫口而出二者的區別。 GET在瀏覽器回退時是無害的…

有贊電商云應用框架設計

背景 有贊是 SaaS 公司&#xff0c;向商家提供了全方位的軟件服務&#xff0c;支撐商家進行采購、店鋪、商品、營銷、訂單、物流等等管理服務。 在這個軟件服務里&#xff0c;能夠滿足大部分的商家&#xff0c;為商家保駕護航。 但是很多大商家往往會有自己的特殊需求&#xff…

vivado 如何創建工程模式_基于Vivado的FPGA高性能開發研修班2019年8月30日上海舉行...

一、課程介紹&#xff1a;從7系列FPGA開始&#xff0c;Xilinx提出了Vivado Design Suite設計軟件&#xff0c;提供全新構建的SoC 增強型、以 IP 和系統為中心的下一代開發環境&#xff0c;以解決系統級集成和實現的生產力瓶頸。同時&#xff0c;Xilinx專門針對Vivado推出了Ultr…

程序員的自我修養——遠離“外包思維”

*************************************優雅的分割線 ********************************** 分享一波:程序員賺外快-必看的巔峰干貨 在我們做開發的日子里&#xff0c;不免會進行跳槽&#xff0c;跳來跳去公司無非就分成兩大類——互聯網公司、外包公司。當然我們本次討論的并…

英特爾為 Kubernetes 推出分布式深度學習平臺:Nauta

2019獨角獸企業重金招聘Python工程師標準>>> 隨著人工智能的發展&#xff0c;深度學習的價值不斷增長&#xff0c;但實現它可能是一個復雜耗時的過程。英特爾(Intel)正尋求通過其在 Kubernetes 進行分布式深度學習的新開源平臺來改變這一狀況&#xff0c;該深度學習…

pytorch梯度下降函數_Pytorch中常用的四種優化器SGD、Momentum、RMSProp、Adam

來源&#xff1a;AINLPer微信公眾號編輯: ShuYini校稿: ShuYini時間: 2019-8-16 引言很多人在使用pytorch的時候都會遇到優化器選擇的問題&#xff0c;今天就給大家介紹對比一下pytorch中常用的四種優化器。SGD、Momentum、RMSProp、Adam。隨機梯度下降法&#xff08;SGD&#…

2019/02/11-分布式數據庫概述

分布式數據庫類型&#xff08;1&#xff09;同構同質型&#xff1a;各場地都是同一種類型的數據庫&#xff0c;如都是關系型數據庫&#xff0c;且都是同一型號的數據庫管理系統&#xff08;2&#xff09;同構異質型&#xff1a;各場地是同一種類型的數據庫&#xff0c;但是數據…

python計算無窮級數求和常用公式_傅里葉變換(二) 從傅里葉級數到傅里葉變換...

在上一部分當中&#xff0c;得到了利用三角函數表示周期函數的方法&#xff0c;但是對于非周期函數就...涼了。所以有什么辦法嗎&#xff1f;沒辦法&#xff08;劃掉&#xff09;。這時候我們就需要拿出來我們的黑科技——傅里葉變換。一、傅里葉級數的推廣當然這東西肯定不是憑…

中鳴投籃機器人怎么組裝_1000余人參加洛陽市青少年機器人競賽

機器人智能識別地面上的黑色線條&#xff0c;并沿著線條來到指定位置&#xff0c;放下“快遞包裹”&#xff1b;無人機在空中飛舞&#xff0c;時而鉆過圓環&#xff0c;時而來個空翻&#xff0c;猶如跳芭蕾般在空中劃過一道優美曲線&#xff1b;橘紅色乒乓球從筒道中送出&#…

Exchange隊列優先級介紹和配置

一、場景 在日常辦公環境中所有郵件都會存在重要與非重要的情況&#xff0c;并且不同的郵箱的使用人的級別也不一樣&#xff0c;不一樣的職位級別要求不一樣的運維等級&#xff0c;以及發送郵件要求的速度也不一樣。這就導致了郵件需要按照重要性進行分類&#xff0c;重要的郵件…

Mybatis源碼閱讀(一):Mybatis初始化1.3 —— 解析sql片段和sql節點

*************************************優雅的分割線 ********************************** 分享一波:程序員賺外快-必看的巔峰干貨 如果以上內容對你覺得有用,并想獲取更多的賺錢方式和免費的技術教程 請關注微信公眾號:HB荷包 一個能讓你學習技術和賺錢方法的公眾號,持續更…

IBM研究院計畫5年改變人類生活創新預測

IBM研究院近日發布未來5年將會改變人類生活方式的5項創新預測&#xff08;IBM 5 in 5&#xff09;&#xff0c;包含透過數字分身&#xff08;Digital Twin&#xff09;農業將用更少的資源供給不斷增長的人口、區塊鏈能防范更多的食物浪費、用微生物基因組群保護人類受到有害細菌…

添加請求頭 retrofit_RxJava 與 Retrofit 結合的最佳實踐

前言RxJava和Retrofit也火了一段時間了&#xff0c;不過最近一直在學習ReactNative和Node相關的姿勢&#xff0c;一直沒有時間研究這些新東西&#xff0c;最近有個項目準備寫&#xff0c;打算先用Android寫一個Demo出來&#xff0c;卻發現Android的世界發生了天翻地覆的變化&am…

Mybatis源碼閱讀(二):動態節點解析2.1 —— SqlSource和SqlNode

*************************************優雅的分割線 ********************************** 分享一波:程序員賺外快-必看的巔峰干貨 如果以上內容對你覺得有用,并想獲取更多的賺錢方式和免費的技術教程 請關注微信公眾號:HB荷包 一個能讓你學習技術和賺錢方法的公眾號,持續更…

k8s邊緣節點_邊緣計算,如何啃下集群管理這塊硬骨頭?

導讀邊緣計算平臺&#xff0c;旨在將邊緣端靠近數據源的計算單元納入到中心云&#xff0c;實現集中管理&#xff0c;將云服務部署其上&#xff0c;及時響應終端請求。然而&#xff0c;成千上萬的邊緣節點散布于各地&#xff0c;例如銀行網點、車載節點等&#xff0c;節點數量甚…

Mybatis源碼閱讀(二):動態節點解析2.2 —— SqlSourceBuilder與三種SqlSource

*************************************優雅的分割線 ********************************** 分享一波:程序員賺外快-必看的巔峰干貨 如果以上內容對你覺得有用,并想獲取更多的賺錢方式和免費的技術教程 請關注微信公眾號:HB荷包 一個能讓你學習技術和賺錢方法的公眾號,持續更…

搞懂toString()與valueOf()的區別

一、toString&#xff08;&#xff09; 作用&#xff1a;toString&#xff08;&#xff09;方法返回一個表示改對象的字符串&#xff0c;如果是對象會返回&#xff0c;toString() 返回 “[object type]”,其中type是對象類型。 二、valueOf( ) 作用&#xff1a;valueOf房啊發返…

oracle入庫的速度能到多少_倒車入庫別練復雜了,其實就這兩點

教練總會讓學員反復練倒車入庫&#xff0c;但不少學員都會有這樣的疑惑&#xff1a;為什么每一次倒庫結果都不一樣&#xff0c;倒車入庫的練習重點是什么&#xff1f;倒車入庫是科二的重點及難點&#xff0c;但只要掌握以下兩個關鍵&#xff0c;順利通過真不難&#xff1a;01方…