摘要:一個(gè)來自于程序設(shè)計(jì)的經(jīng)典問題。注意事項(xiàng)負(fù)數(shù)問題。和上一點(diǎn)是一樣的問題,要確定方式是屬于具體的對(duì)象,還是屬于一個(gè)類。
1.初見一個(gè)來自于C++程序設(shè)計(jì)的經(jīng)典問題。如何定義一個(gè)分?jǐn)?shù)類,實(shí)現(xiàn)分?jǐn)?shù)的約分化簡,分?jǐn)?shù)之間的加法、減法、乘法、除法四則運(yùn)算?
剛看到這道題的時(shí)候,第一感覺是挺簡單的啊,就是基本的面向?qū)ο螅x對(duì)應(yīng)的加減乘除類就可以了啊,然而到了實(shí)現(xiàn)的時(shí)候才發(fā)現(xiàn)許多問題是說起來容易做起來難,在實(shí)現(xiàn)的過程中,發(fā)現(xiàn)了許多的注意點(diǎn),以及算法。
最終得出結(jié)論:這個(gè)問題著實(shí)是考察程序員基本功的一道好題。
2.整體思路分?jǐn)?shù)類設(shè)計(jì)的總體思路如下:
首先是分?jǐn)?shù)的表示,這就需要利用兩個(gè)變量保存分?jǐn)?shù)的分子和分母;
其次是約分和通分,由于分?jǐn)?shù)四則運(yùn)算中需要借助約分和通分來實(shí)現(xiàn),因此必須先考慮實(shí)現(xiàn)這兩個(gè)算法。
加法和乘法的實(shí)現(xiàn)。利用約分和通分就可以輕松實(shí)現(xiàn)。
減法和除法的實(shí)現(xiàn)。是加法和乘法的逆運(yùn)算。和直接轉(zhuǎn)化為加法和乘法。
3.注意事項(xiàng)負(fù)數(shù)問題。這個(gè)問題十分重要,在我們的算法中,都規(guī)定分母為正數(shù),如果出現(xiàn)了分母為負(fù)數(shù)的情況,就分子分母同時(shí)乘以-1,把負(fù)數(shù)運(yùn)算放在分子上。
函數(shù)的副作用(side effect)。盡量不要在方法中改變?cè)瓉矸謹(jǐn)?shù)的值,否則會(huì)產(chǎn)生副作用,導(dǎo)致后面的運(yùn)算出錯(cuò),在代碼中會(huì)說明。
靜態(tài)方法和動(dòng)態(tài)方法。和上一點(diǎn)是一樣的問題,要確定方式是屬于具體的對(duì)象,還是屬于一個(gè)類。
除法運(yùn)算中,除數(shù)不能等于0
4.代碼實(shí)現(xiàn) 4.1 屬性和構(gòu)造方法構(gòu)造方法中有三個(gè)細(xì)節(jié):一是使用了參數(shù)默認(rèn)值,默認(rèn)不寫參數(shù)時(shí),讓分子分母都等于1;二是在構(gòu)造方法中進(jìn)行了分母合法性的驗(yàn)證,分母等于0時(shí)直接返回錯(cuò)誤信息;三是對(duì)負(fù)值進(jìn)行了處理,使分?jǐn)?shù)的分母永遠(yuǎn)為正數(shù),方便后續(xù)運(yùn)算。
/** * 分?jǐn)?shù)運(yùn)算類 */ class Fraction { //定義分子和分母 public $fenzi; public $fenmu; //構(gòu)造函數(shù) function __construct($fenzi = 1,$fenmu = 1) { if ($fenmu == 0) { return "分母不能為0"; } if ($fenmu < 0) { $fenmu = -$fenmu; $fenzi = -$fenzi; } $this->fenzi = $fenzi; $this->fenmu = $fenmu; } }4.2 最大公約數(shù)和最小公倍數(shù)
為了后續(xù)的約分和通分,必須先求出最大公約數(shù)和最小公倍數(shù)。求最大公約數(shù)采用輾轉(zhuǎn)相除法,而最小公倍數(shù)由以下公式可求:
最小公倍數(shù) = (數(shù)A * 數(shù)B)/ 最大公約數(shù)
//求最大公約數(shù)用于約分 private static function _getmax($a, $b) { if($a < 0) $a = -$a; if($b < 0) $b = -$b; $tmp = $a % $b; while($tmp != 0) { $a = $b; $b = $tmp; $tmp = $a % $b; } return $b; } //求最小公倍數(shù)用于通分 private static function _getmin($a, $b) { if($a < 0) $a = -$a; if($b < 0) $b = -$b; $max = self::_getmax($a,$b); $min = intval(($a * $b) / $max); return $min; } /** * 約分運(yùn)算,基本算法為分子分母同時(shí)除以最大公約數(shù); * @return void 將對(duì)象的分子分母約分為最簡形式 */ public function reduction() { $max = $this->_getmax($this->fenzi,$this->fenmu); $this->fenzi = intval($this->fenzi / $max); $this->fenmu = intval($this->fenmu / $max); }
這兩個(gè)方法全部都定義為靜態(tài)私有方法,只在類內(nèi)調(diào)用且不需實(shí)例化。求最大公約數(shù)和最小公倍數(shù)的算法其實(shí)還有很多種,@燼醬采用了另外一種方法,C++代碼如下:
/** * 求最大公約數(shù)并進(jìn)行約分 * @return void */ int reduction() { int i,comdiv,small,max; if(above1;i--) { if(small%i==0 &max%i==0 ) break; } comdiv=i; //最大公約數(shù) if(i!=0) { above/=i; below/=i; } return 0; }
這種方法的本質(zhì)就窮盡法,核心思想在于for循環(huán)當(dāng)中。同樣的,也可用此法求最小公倍數(shù)。
4.3 分?jǐn)?shù)加減分?jǐn)?shù)加法的算法如下:
/** * 加法運(yùn)算,寫成靜態(tài)方法,需要傳遞兩個(gè)分?jǐn)?shù)對(duì)象實(shí)例。加法的基本步驟為: * 1. 求兩個(gè)分母的最小公倍數(shù); * 2. 利用最小公倍數(shù)進(jìn)行通分,此時(shí)分母就是最小公倍數(shù),第一個(gè)分?jǐn)?shù)的分子等于原來的分子*(最小公倍數(shù)/原來的分母),第二個(gè)分?jǐn)?shù)的分子同理; * 3. 分母不變,分子相加; * 4. 對(duì)結(jié)果進(jìn)行約分; * * @param fraction $fra1 分?jǐn)?shù)相加的加數(shù)1 * @param fraction $fra2 分?jǐn)?shù)相加的加數(shù)2 * @return fraction $fra 分?jǐn)?shù)相加的計(jì)算結(jié)果 */ public static function add($fra1, $fra2) { $fra = new Fraction(); $min = self::_getmin($fra1->fenmu,$fra2->fenmu); $fenzi_left = $fra1->fenzi * ($min / $fra1->fenmu); $fenzi_right = $fra2->fenzi * ($min / $fra2->fenmu); $fra->fenmu = $min; $fra->fenzi = $fenzi_left + $fenzi_right; $fra->reduction(); return $fra; } /** * 減法運(yùn)算,加法的逆運(yùn)算,只需要將參數(shù)$fra2的分子取反,將減法運(yùn)算化為加法運(yùn)算 * * @param fraction $fra1 分?jǐn)?shù)相減的被減數(shù) * @param fraction $fra2 分?jǐn)?shù)相減的減數(shù) * @return fraction $fra 分?jǐn)?shù)相減的計(jì)算結(jié)果 */ public static function minus($fra1, $fra2) { $fra_t = new Fraction(-$fra2->fenzi,$fra2->fenmu); return self::add($fra1,$fra_t); }
在上述算法中,定義了兩個(gè)靜態(tài)方法,每個(gè)方法需要傳入兩個(gè)分?jǐn)?shù)對(duì)象,之后就可以按上面的算法步驟進(jìn)行加法和減法運(yùn)算了。其中減法運(yùn)算只需要轉(zhuǎn)換為加法即可。需要注意的是,在減法運(yùn)算中,存在兩種可能的寫法:
【寫法1】
$fra2->fenzi = -$fra2->fenzi;
【寫法2】
$fra_t = new Fraction(-$fra2->fenzi,$fra2->fenmu);
其中,第一種寫法直接改變了減數(shù)分子的值,這里對(duì)減法本身的結(jié)果不會(huì)造成影響,表面上看是成立的,但其實(shí)這種寫法產(chǎn)生了副作用,在計(jì)算乘法時(shí),fra2就已經(jīng)不是最初的分?jǐn)?shù)值了,因此我們需要new一個(gè)新的對(duì)象,如寫法2所示,這樣就不會(huì)產(chǎn)生副作用改變分?jǐn)?shù)2的值。
4.4 分?jǐn)?shù)乘除分?jǐn)?shù)乘數(shù)就比較簡單了,如下所示:
/** * 乘法運(yùn)算,分子相乘,分母相乘之后再約分 * * @param fraction $fra1 分?jǐn)?shù)相乘的乘數(shù)1 * @param fraction $fra2 分?jǐn)?shù)相乘的乘數(shù)2 * @return fraction $fra 分?jǐn)?shù)相乘的計(jì)算結(jié)果 */ public static function multiply($fra1,$fra2) { $fra = new Fraction(); $fenzi = $fra1->fenzi * $fra2->fenzi; $fenmu = $fra1->fenmu * $fra2->fenmu; $fra->fenzi = $fenzi; $fra->fenmu = $fenmu; $fra->reduction(); return $fra; } /** * 除法運(yùn)算,乘法運(yùn)算的逆運(yùn)算,只需要將參數(shù)$fra2的分子分母調(diào)換,將除法運(yùn)算化為乘法運(yùn)算 * * @param fraction $fra1 分?jǐn)?shù)相除的被除數(shù) * @param fraction $fra2 分?jǐn)?shù)相除的除數(shù) * @return fraction 分?jǐn)?shù)相除的計(jì)算結(jié)果 */ public static function divide($fra1,$fra2) { $fra_t = new Fraction($fra2->fenmu,$fra2->fenzi); $fra = self::multiply($fra1,$fra_t); return $fra; }4.5 分?jǐn)?shù)的表示
最后,我們需要寫一個(gè)方法,把分?jǐn)?shù)以a/b的形式打印出來。
public function display() { printf("%d/%d ",$this->fenzi,$this->fenmu); }
這樣我們的分?jǐn)?shù)類的定義完了。
5. 結(jié)果展示下面展示運(yùn)行結(jié)果,先寫一個(gè)調(diào)用:
$fra1 = new Fraction(3,4); $fra1->display(); $fra2 = new Fraction(12,20); $fra2->reduction(); $fra2->display(); $fra3 = Fraction::add($fra1,$fra2); $fra3->display(); $fra4 = Fraction::minus($fra1,$fra2); $fra4->display(); $fra5 = Fraction::multiply($fra1,$fra2); $fra5->display(); $fra6 = Fraction::divide($fra1,$fra2); $fra6->display();
如上,fra1期望直接打印出3/4, fra2對(duì)12/20先約分再輸出,期望是3/5,fra3是計(jì)算fra1和fra2的加法,fra4為減法,fra5為乘法,fra6為除法。結(jié)果如下所示:
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/30348.html
摘要:最后,我們顯示了若干張圖像中所生成的趣味字幕。圖所提出的有趣字幕生成的體系結(jié)構(gòu)。我們將所提出的方法稱為神經(jīng)玩笑機(jī)器,它是與預(yù)訓(xùn)練模型相結(jié)合的。用戶對(duì)已發(fā)布的字幕的趣味性進(jìn)行評(píng)估,并為字幕指定一至三顆星。 可以毫不夸張地說,笑是一種特殊的高階功能,且只有人類才擁有。那么,是什么引起人類的笑聲表達(dá)呢?最近,日本東京電機(jī)大學(xué)(Tokyo Denki University)和日本國家先進(jìn)工業(yè)科學(xué)和技...
摘要:本文討論了多個(gè)評(píng)估指標(biāo),并從多個(gè)方面對(duì)評(píng)估指標(biāo)進(jìn)行了實(shí)驗(yàn)評(píng)估,包括距離分類器。鑒于定性評(píng)估的內(nèi)在缺陷,恰當(dāng)?shù)亩吭u(píng)估指標(biāo)對(duì)于的發(fā)展和更好模型的設(shè)計(jì)至關(guān)重要。鑒于評(píng)估非常有難度,評(píng)估評(píng)估指標(biāo)則更加困難。 作者:Qiantong Xu、Gao Huang、Yang Yuan、Chuan Guo、Yu Sun、Felix Wu、Kilian Weinberger生成對(duì)抗網(wǎng)絡(luò)的評(píng)估目前仍以定性評(píng)估和...
摘要:我們?cè)谇拔闹锌紤]的那張圖就來自這篇文章,之后我們會(huì)用剪枝算法來改進(jìn)之前的解決方案。剪枝算法的實(shí)現(xiàn)接下來討論如何修改前面實(shí)現(xiàn)的算法,使其變?yōu)榧糁λ惴ā,F(xiàn)在我們已經(jīng)有了現(xiàn)成的和剪枝算法,只要加上一點(diǎn)兒細(xì)節(jié)就能完成這個(gè)游戲了。 前段時(shí)間用 React 寫了個(gè)2048 游戲來練練手,準(zhǔn)備用來回顧下 React 相關(guān)的各種技術(shù),以及試驗(yàn)一下新技術(shù)。在寫這個(gè)2048的過程中,我考慮是否可以在其中加...
摘要:我們?cè)谇拔闹锌紤]的那張圖就來自這篇文章,之后我們會(huì)用剪枝算法來改進(jìn)之前的解決方案。剪枝算法的實(shí)現(xiàn)接下來討論如何修改前面實(shí)現(xiàn)的算法,使其變?yōu)榧糁λ惴ā,F(xiàn)在我們已經(jīng)有了現(xiàn)成的和剪枝算法,只要加上一點(diǎn)兒細(xì)節(jié)就能完成這個(gè)游戲了。 前段時(shí)間用 React 寫了個(gè)2048 游戲來練練手,準(zhǔn)備用來回顧下 React 相關(guān)的各種技術(shù),以及試驗(yàn)一下新技術(shù)。在寫這個(gè)2048的過程中,我考慮是否可以在其中加...
摘要:如果做推薦系統(tǒng)不知道基于物品的協(xié)同過濾,那等同于做程序員不懂得冒泡排序。基于物品的八卦基于物品的協(xié)同過濾算法誕生于年,是由亞馬遜首先提出的,并在年由其發(fā)明者發(fā)表了相應(yīng)的論文。 不管你有沒有剁過手,你對(duì)看了這個(gè)商品的還看了這樣的推薦形式一定不陌生。無論是貓還是狗,或者是其他電商網(wǎng)站,這樣的推薦產(chǎn)品可以說是推薦系統(tǒng)的標(biāo)配了。 類似的還有,如點(diǎn)評(píng)標(biāo)記類網(wǎng)站的喜歡了這部電影的還喜歡了,社交媒...
閱讀 3424·2021-10-20 13:49
閱讀 2799·2021-09-29 09:34
閱讀 3697·2021-09-01 11:29
閱讀 3084·2019-08-30 11:01
閱讀 840·2019-08-29 17:10
閱讀 880·2019-08-29 12:48
閱讀 2782·2019-08-29 12:40
閱讀 1353·2019-08-29 12:30