數學與泛型程式設計(1)埃及乘法 加法鏈

2021-10-11 02:21:05 字數 3604 閱讀 5812

一看到這書的書名就被深深吸引了啊!怎麼會有這種書!!!

數學與泛型程式設計(1)埃及乘法、加法鏈   

數學與泛型程式設計(2)群   

數學與泛型程式設計(3)推導泛型演算法   

數學與泛型程式設計(4)環   

數學與泛型程式設計(5)域   

數學與泛型程式設計(6)程式設計的基本概念   

數學與泛型程式設計(7)置換演算法   

數學與泛型程式設計(8)理想   

目錄

1,什麼是泛型程式設計

2,泛型的思想**

3,演算法的起源 vs 數學的起源

4,列豎式計算乘法 vs 埃及乘法

5,十進位制 vs 二進位制

6,加法鏈

7,嚴格尾遞迴

泛型程式設計是一種專注於對演算法及資料結構進行設計的程式設計方式,它使得這些演算法及資料結構能夠在不損失效率的前提下,運用到最為通用的環境中。

這種想法是從個數學中衍生出來的,尤其與抽象代數這個數學分支有關。

抽象代數裡面的抽象很大程度上是從另外乙個數學分支的具體成果中得出的,那個分支比抽象代數更為古老,它叫做數論。

要想成為優秀的程式設計師,就必須理解泛型程式設計的原則;要想理解泛型程式設計的原則,就必須學會抽象;要想學會抽象,就必須知道它所依據的數學基礎。

演算法(algorithm)是用來完成計算任務的一系列有限步驟。由於演算法與計算機程式設計的關係特別密切,因此很多人或許認為,演算法是乙個來自電腦科學專業的概念。其實演算法這個詞已經有幾千年歷史了。數學中充滿了各種各樣的演算法,有些演算法我們天天在用,就連小學生計算加法時所用的豎式(long addition)都可以說是一種演算法。

儘管演算法的歷史很悠久,但它並不是天生就有的,而是由人發明出來的。雖然我們並不清楚第乙個發明演算法的人是誰,但我們知道,早在四千多年前埃及就已經有了某些演算法。

在我們的通常觀念中,邏輯簡單的問題是不需要演算法的,需要演算法的都是邏輯比較複雜的問題(比如oj上的題目)

幾千年前,人們用繩子計數,在這個時代,乘法就是乙個比較困難的問題,需要演算法。

埃及乘法/俄羅斯農夫演算法

這種演算法所依據的原理是:4a = ((a+a)+a)+a = (a+a) + (a+a), 這個原理是根據加法結合律推算出來的。

如果採用這個辦法,那麼只需把a+a的值計算一次就行了,這樣可以降低加法運算的次數。

埃及乘法演算法的思路是:反覆地將n減半,並將a加倍,同時求出a的各種倍數,這些倍數與a的比值都是2的整數次冪。

41*59 = 1*59 + 8*59 + 32*59

由於該演算法在將n減半的時候需要判斷n是奇數還是偶數,因此儘管沒有直接的證據,但我們依然能夠推測出:古埃及人已經知道了奇數和偶數之間的區別。

埃及乘法,在acm裡面一般叫做快速乘法(演算法和快速冪差不多,所以叫法一致)

#define ll long long

ll g(ll a, ll b, ll p)//a*b

快速乘法參考:csu 1162: balls in the boxes(快速冪、快速乘法)

列豎式計算兩位數的乘法大概是這樣的:

誒及乘法用二進位制表示大概是這樣的:

當然,誒及乘法和二進位制列豎式乘法還是有差異的,誒及乘法不涉及進製轉換,所以上圖的上面一半是二進位制列豎式乘法,下面一半才是埃及乘法

列豎式計算乘法 和 埃及乘法 在泛進製的角度上來看是一樣的。

(1)為什麼人類使用十進位制,機器使用二進位制?

因為人類有十個手指頭,機器的電路有開關兩種狀態,各自用各自方便的進製基數。

(2)列豎式計算乘法是怎麼來的?

並不是每個國家的小學生計算兩位數的乘法的方法都和中國一樣,甚至據說有些國家的學生到了小學畢業還是覺得計算乘法很難,因為他們的計算方法不一樣,而且據說別的語言的九九乘法表沒有漢語這麼順口好記。

我推測,應該是在有了阿拉伯數字和九九乘法表之後,埃及乘法就被合理改造成列豎式計算乘法了。

從這個角度來說,埃及乘法計算乙個泛型演算法,進製就是資料結構的差異,就好像max函式可以傳入int也可以傳入double一樣。

補更:我在本書中剛好發現了這個科普:

0的突破發生在公元2023年。這一年,比薩的列奧那多(leonardo pisano,也稱為斐波那契,fibonacci)出版了一本名為《計算之書》(liber abaci)的著作,其中不僅介紹了0與十進位制位值計數法,而且首次向歐洲人講述了算術運算的標準步驟,也就是怎樣用豎式來計算加減乘除,這些步驟直到今天依然在小學課堂上傳授。我們可以說,列奧那多一舉將數學帶回了歐洲。

(3)埃及乘法是二進位制嗎?

二進位制應該是近代才發明的,據說是牛頓的老對手萊布尼茨發明的。

埃及乘法被發明的時候沒有二進位制,用繩子計數只有加減法,沒有很強的乘法的概念,更沒有除法,也更不會涉及進製轉換了。

為什麼埃及演算法剛好契合二進位制呢?因為,加法是二元操作符,而且,繩子計數可以很快的進行除2操作!

雖然沒有除法,但是把繩子對折,這就是天然的除2啊,書中也提到,這個時候的人們應該已經有奇數和偶數的概念了。

書中也提到相關概念,這種乘法是依賴加法結合律的,也就是a+a+a+a+a+a = (a+a) + (a+a) + (a+a) 

看到了嗎?每個括號都是把2個數括起來,讓6個數相加的問題變成了3個數相加的問題。

這裡指的是乙個如何計算nx,其中n是已知數,而x是未知數,設計乙個對x通用的演算法。

(1)埃及乘法的加法次數

設n是乙個a位的二進位制數,這a位由b個1和a-b個0組成,那麼埃及乘法計算nx的過程中,加法的次數是a+b-2

用函式來表示:aj(n) = a+b-2

當n是1到15時,函式值分別是0,1,2,2,3,3,4,3,4,4,5,4,5,5,6

顯然,aj函式並不是遞增函式

(2)加法鏈

埃及乘法的加法次數是最少的嗎?這個演算法是最優的嗎?

書中給出了反例,顯然也是最小的反例:

這個程式其實是先算出b=3x,需要2次加法,再算出5b,需要3次加法,一共需要5次加法

這樣一種計算乘法的方式叫做加法鏈,埃及乘法本身也是一種加法鏈(長度為1的鏈)

(3)最優加法鏈

按照加法鏈的方式計算乘法,需要的最少加法次數記為l(n)

如果乙個加法鏈,用它計算乘法需要的加法次數是l(n),那麼它就是最優加法鏈

(4)l函式的性質

l(x)<= aj(x)

l(yz)<= l(y) + l(z)

l(x+1)<=l(x)+1

l(2x)=l(x)+1

設rl(x)=min{l(y)+l(x/y)|y是x的約數,1如此,我們就可以算出最優加法鏈了。

嚴格的尾遞迴過程,是指那種使用與形式引數完全對應的實際引數,來進行所有遞迴呼叫的尾遞迴過程。

把遞迴程式寫成嚴格尾遞迴,就比較容易轉化成非遞迴寫法了。

Boolan C STL與泛型程式設計 1

c 標準庫 體系結構與核心分析 主要內容 本節主要對c 標準庫學習的4個階段,c 標準庫和新舊式c的標頭檔案,以及stl進行講解。stl是泛型程式設計最成功的作品。stl屬於c 標準庫的一部分,它具有容器 演算法 介面卡 分配器 迭代器 泛函式等六大部件。使用乙個東西,卻不明白它的道理,不高明。林語...

《數學與泛型程式設計 高效程式設計的奧秘》一導讀

如果將電腦科學與數學分離,那麼這兩者的發展都會有很大困難。於是,我們就試圖通過一些課程,把人類文明早期就有的數學活動與現代才有的計算機活動結合起來。本書正是基於這樣一種課程而編寫的。能夠與友人dan rose合作,我深感榮幸。他的管理工作令我們團隊能夠把泛型程式設計的原則運用到搜尋引擎的設計上來,而...

第16章 模板與泛型程式設計 1

所謂泛型程式設計就是以獨立於任何特定型別的方式編寫 模板是泛型程式設計的基礎。模板是建立類或函式的藍圖或公式。物件導向程式設計所依賴的多型性稱為執行時多型性,泛型程式設計所依賴的多型性稱為編譯時多型性或引數式多型性。16.1 模板定義 我們可以不用為每個型別定義乙個新函式,而是只定義乙個函式模板 f...