導航:首頁 > 編程知識 > 在編程中怎麼調叫用數數

在編程中怎麼調叫用數數

發布時間:2024-01-18 08:02:04

⑴ 誰能告訴我如何用計算機編程的語言比如1和0表示出1到10的數字

本文字數:4894 字
閱讀本文大概需要:13 分鍾

寫在之前

我們都知道,對於同一個問題來說,可以有多種解決問題的演算法。盡管演算法不是唯一的,但是對於問題本身來說相對好的演算法還是存在的,這里可能有人會問區分好壞的標準是什麼?這個要從「時效」和「存儲」兩方面來看。

人總是貪婪的,在做一件事的時候,我們總是期望著可以付出最少的時間、精力或者金錢來獲得最大的回報,這個類比到演算法上也同樣適用,那就是花最少的時間和最少的存儲做成最棒的解決辦法,所以好的演算法應該具備時效高和存儲低的特點。這里的「時效」是指時間效率,也就是演算法的執行時間,對於同一個問題的多種不同解決演算法,執行時間越短的演算法效率越高,越長的效率越低;「存儲」是指演算法在執行的時候需要的存儲空間,主要是指演算法程序運行的時候所佔用的內存空間。

時間復雜度

首先我們先來說時間效率的這個問題,這里的時間效率就是指的演算法的執行時間,時間的快慢本來就是一個相對的概念,那麼到了演算法上,我們該用怎樣的度量指標去度量一個演算法的時間效率(執行時間)呢?

剛開始我們想出了一種事後統計方法,我稱它為「馬後炮式」,顧名思義,就是對於要解決的某個問題,費盡心思想了 n 種解法,提前寫好演算法程序,然後攢了一堆數據,讓它們分別在電腦上跑,跑完瞭然後比較程序的運行時間,根據這個來判斷演算法時效的高低。這種的判斷技術計算的是我們日常所用的時間,但這並不是一個對我們來說有用的度量指標,因為它還依賴於運行的機器、所用的編程語言、編譯器等等等等。相反,我們需要的是一個不依賴於所用機器或者編程語言的度量指標,這種度量指標可以幫助我們判斷演算法的優劣,並且可以用來比較演算法的具體實現。

我們的科學家前輩們發現當我們試圖去用執行時間作為獨立於具體程序或計算機的度量指標去描述一個演算法的時候,確定這個演算法所需要的步驟數目非常重要。如果我們把演算法程序中的每一步看作是一個基本的計量單位,那麼一個演算法的執行時間就可以看作是解決一個問題所需要的總步驟數。但是由於演算法的執行過程又各不相同,所以這個每一步,即這個基本的計量單位怎麼去選擇又是一個令人頭禿的問題。

下面我們來看一個簡單的求和的函數:

defget_sum(n): sum = 0for i in range(1,n+1): sum += i return sumprint(get_sum(10))

我們仔細去分析一下上述代碼,其實可以發現統計執行求和的賦值語句的次數可能是一個好的基本計數單位,在上面 get_sum 函數中,賦值語句的數量是 1 (sum = 0)加上 n (執行 sum += i 的次數)。

我們一般用一個叫 T 的函數來表示賦值語句的總數量,比如上面的例子可以表示成 T(n) = n + 1。這里的 n 一般指的是「數據的規模大小」,所以前面的等式可以理解為「解決一個規模大小為 n,對應 n+1 步操作步數的問題,所需的時間為 T(n)」。

對於 n 來說,它可以取 10,100,1000 或者其它更大的數,我們都知道求解大規模的問題所需的時間比求解小規模要多一些,那麼我們接下來的目標就很明確了,那就是「尋找程序的運行時間是如何隨著問題規模的變化而變化」。

我們的科學家前輩們又對這種分析方法進行了更為深遠的思考,他們發現有限的操作次數對於 T(n) 的影響,並不如某些占據主要地位的操作部分重要,換句話說就是「當數據的規模越來越大時,T(n) 函數中的某一部分掩蓋了其它部分對函數的影響」。最終,這個起主導作用的部分用來對函數進行比較,所以接下來就是我們所熟知的大 O閃亮登場的時間了。

大 O 表示法

「數量級」函數用來描述當規模 n 增加時,T(n) 函數中增長最快的部分,這個數量級函數我們一般用「大 O」表示,記做 O(f(n))。它提供了計算過程中實際步數的近似值,函數 f(n) 是原始函數 T(n) 中主導部分的簡化表示。

在上面的求和函數的那個例子中,T(n) = n + 1,當 n 增大時,常數 1 對於最後的結果來說越來不越沒存在感,如果我們需要 T(n) 的近似值的話,我們要做的就是把 1 給忽略掉,直接認為 T(n) 的運行時間就是 O(n)。這里你一定要搞明白,這里不是說 1 對 T(n) 不重要,而是當 n 增到很大時,丟掉 1 所得到的近似值同樣很精確。

再舉個例子,比如有一個演算法的 T(n) = 2n^2+ 2n + 1000,當 n 為 10 或者 20 的時候,常數 1000 看起來對 T(n) 起著決定性的作用。但是當 n 為 1000 或者 10000 或者更大呢?n^2 起到了主要的作用。實際上,當 n 非常大時,後面兩項對於最終的結果來說已經是無足輕重了。與上面求和函數的例子很相似,當 n 越來越大的時候,我們就可以忽略其它項,只關注用 2n^2 來代表 T(n) 的近似值。同樣的是,系數 2 的作用也會隨著 n 的增大,作用變得越來越小,從而也可以忽略。我們這時候就會說 T(n) 的數量級 f(n) = n^2,即 O(n^2)。

最好情況、最壞情況和平均情況

盡管前面的兩個例子中沒有體現,但是我們還是應該注意到有時候演算法的運行時間還取決於「具體數據」而不僅僅是「問題的規模大小」。對於這樣的演算法,我們把它們的執行情況分為「最優情況」、「最壞情況」和「平均情況」。

某個特定的數據集能讓演算法的執行情況極好,這就是最「最好情況」,而另一個不同的數據會讓演算法的執行情況變得極差,這就是「最壞情況」。不過在大多數情況下,演算法的執行情況都介於這兩種極端情況之間,也就是「平均情況」。因此一定要理解好不同情況之間的差別,不要被極端情況給帶了節奏。

對於「最優情況」,沒有什麼大的價值,因為它沒有提供什麼有用信息,反應的只是最樂觀最理想的情況,沒有參考價值。「平均情況」是對演算法的一個全面評價,因為它完整全面的反映了這個演算法的性質,但從另一方面來說,這種衡量並沒有什麼保證,並不是每個運算都能在這種情況內完成。而對於「最壞情況」,它提供了一種保證,這個保證運行時間將不會再壞了,**所以一般我們所算的時間復雜度是最壞情況下的時間復雜度**,這和我們平時做事要考慮到最壞的情況是一個道理。

在我們之後的演算法學習過程中,會遇到各種各樣的數量級函數,下面我給大家列舉幾種常見的數量級函數:

為了確定這些函數哪些在 T(n) 中佔主導地位,就要在 n 增大時對它們進行比較,請看下圖(圖片來自於 Google 圖片):

在上圖中,我們可以看到當 n 很小時,函數之間不易區分,很難說誰處於主導地位,但是當 n 增大時,我們就能看到很明顯的區別,誰是老大一目瞭然:

O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n)

我們下面就來分析幾個上述所說的「數量級函數」:

1.常數函數

n = 100 # 1 次sum = (1 + n) *n / 2 # 1 次print(sum) # 1 次

上述演算法程序的 f(n) = 3,可能有人看到這會說那麼時間復雜度就是 O(f(n)) = O(3),其實這個是錯的,這個函數的時間復雜度其實是 O(1)。這個對於初學者來說是很難理解的一種結果,其實你可以把 sum = (1 + n) * n / 2 多復制幾次再來看:

a = 100 # 1 次sum = (1 + n) * n / 2 # 1 次sum = (1 + n) * n / 2 # 1 次sum = (1 + n) * n / 2 # 1 次sum = (1 + n) * n / 2 # 1 次sum = (1 + n) * n / 2 # 1 次sum = (1 + n) * n / 2 # 1 次print(sum) # 1 次

上述演算法的 f(n) = 8,事實上你可以發現無論 n 為多少,上述兩段代碼就是 運行 3 次和運行 8 次的區別。這種與數據的規模大小 n 無關,執行時間恆定的演算法我們就叫它具有 O(1) 的時間復雜度。不管這個常數是多少,我們都記作是 O(1),而不是 O(3) 或者是 O(8)。

2.對數函數

cnt = 1while cnt < n: cnt *= 2 # O(1)

上面的演算法程序的時間復雜度就是 O(logn),這個是怎麼算出來的呢?其實很簡單:上述的代碼可以解釋成 cnt 乘以多少個 2 以後才能大於等於 n,我們假設個數是 x,也就是求 2^x = n,即 x = log2n,所以這個循環的時間復雜度就是 O(logn)。

最後呢,我們來看看下面的這個例子,藉助這段代碼來詳細的說一下我們如何對其時間復雜度進行詳細的分析:

a = 1b = 2c = 3for i inrange(n):for j inrange(n): x = i * i y = j * j z = i * jfor k inrange(n): u = a * k + b v = c * cd = 4

上面的代碼沒有任何意義,甚至不是一個可運行的代碼,我只是用來說明你在以後如何對代碼進行執行分析,關於代碼本身可不可以運行,就不需要你在這關心了。

上面的代碼其實我們要分的話可以分成 4 部分:第 1 部分是 a,b,c 這 3 個賦值語句,執行次數也就是 3 次;第二部分是 3n^2,因為是循環結構,裡面有 x,y,z 這 3 個賦值語句,每個語句執行了 n^2 次;第 3 部分是 2n,因為裡面是 2 個賦值語句,每條語句被執行了 n 次;最後第 4 部分是常數 1,只有 d 這么 1 條賦值語句。所以我們得到的 T(n
) = 3+3n^2 +2n+1 = 3n^2+2n+4,看到指數項,我們自然的發現是 n^2 做主導,當 n 增大時,後面兩項可以忽略掉,所以這個代碼片段的數量級就是 O(n^2)。

空間復雜度

類比於時間復雜度的討論,一個演算法的空間復雜度是指該演算法所耗費的存儲空間,計算公式計作:S(n) = O(f(n))。其中 n 也為數據的規模,f(n) 在這里指的是 n 所佔存儲空間的函數。

一般情況下,我們的程序在機器上運行時,刨去需要存儲程序本身的輸入數據等之外,還需要存儲對數據操作的「存儲單元」。如果輸入數據所佔空間和演算法無關,只取決於問題本身,那麼只需要分析演算法在實現過程中所佔的「輔助單元」即可。如果所需的輔助單元是個常數,那麼空間復雜度就是 O(1)。

空間復雜度其實在這里更多的是說一下這個概念,因為當今硬體的存儲量級比較大,一般不會為了稍微減少一點兒空間復雜度而大動干戈,更多的是去想怎麼優化演算法的時間復雜度。所以我們在日常寫代碼的時候就衍生出了用「空間換時間」的做法,並且成為常態。比如我們在求解斐波那契數列數列的時候我們可以直接用公式去遞歸求,用哪個求哪個,同樣也可以先把很多結果都算出來保存起來,然後用到哪個直接調用,這就是典型的用空間換時間的做法,但是你說這兩種具體哪個好,偉大的馬克思告訴我們「具體問題具體分析」。

寫在之後

如果上面的文章你仔細看了的話,你會發現我不是直接上來就告訴你怎麼去求時間復雜度,而是從問題的產生,到思考解決的辦法,到「馬後炮」,再到 T(n),最後到 O(n)一步一步來的。這樣做的原因呢有兩個:一是為了讓你了解大 O 到底是怎麼來的,有時候搞明白了由來,對於你接下來的學習和理解有很大的幫助;二是為了讓這個文章看起來不是那麼枯燥,我覺得很多時候上來扔給你一堆概念術語,很容易就讓人在剛看到它的時候就打起了退堂鼓,循序漸進的來,慢慢引導著更容易接受一些。

很多人從大學到工作,代碼寫了不少依然不會估算時間復雜度,我感覺倒不是學不會,而是內心沒有重視起來。你可能覺得計算機的更新換代很快,CPU 處理速度的能力越來越棒,沒必要在一些小的方面斤斤計較,其實我覺得你是 too young too naive。我們隨便來算一個簡單的例子:有兩台電腦,你的電腦的運算速度是我的電腦的 100 倍,同樣一道問題,明明稍微想一想用 O(n) 可以做出來,你偏偏要懶,直接暴力 O(n^2),那麼當 n 的數據稍微增大一些,比如上萬上十萬,到底誰的運算速度快還用我再告訴你嗎?

所以今後在寫演算法的時候,請好好學會用時間復雜度估算一下自己的代碼,然後想想有沒有更有效率的方法去改進它,你只要這樣做了,相信慢慢的你的代碼會寫的越來越好,頭會越來越禿。(逃

最後說一點的是,估算演算法的復雜度這件事你不要指望一下子看了一篇文章就想弄懂,這個還是要有意識的多練,比如看到一個程序的時候有意識的估算一下它的復雜度,准備動手寫代碼的時候也想想有沒有更好的優化方法,有意識的練習慢慢就會來了感覺。這篇文章我就用了幾個小例子,大概的估算方式就是這樣。之後我還會繼續寫一些關於「數據結構與演算法」相關的文章和一些具體的實戰題目,都會帶大家繼續分析它們的時間復雜度,敬請期待。

⑵ C語言中count該怎麼用

函數COUNT在計數時,將把數字、空值、邏輯值、日期或以文字代表的數計算進去;但是錯誤值或其他無法轉化成數字的文字則被忽略。

如果參數是一個數組或引用,那麼只統計數組或引用中的數字;數組中或引用的空單元格、邏輯值、文字或錯誤值都將忽略。如果要統計邏輯值、文字或錯誤值,請使用函數COUNTA。

示例

如果A1為1,A5為3,A7為2,其他均為空,則:

COUNT(A1:A7)等於3

COUNT(A4:A7)等於2

COUNT(A1:A7,2)等於4

特殊例子

COUNT(A1:A7,,TRUE,FALSE)等於6

原因:TRUE和FALSE計算機會轉換為1與0所以也是數字。注意兩個逗號間的空白,也默認為數字。

(2)在編程中怎麼調叫用數數擴展閱讀:

代碼:

#include&lt;stdio.h&gt;

int main()

{

int i;

printf("輸入整數:");

scanf("%d",&i);

printf("%d",i);

int count=0;

while(i!=0){

count+=i&1;

i&gt;&gt;=1;

}

printf("的二進製表示中1的位數共有%d: ",count);

return 0;

}

閱讀全文

與在編程中怎麼調叫用數數相關的資料

熱點內容
word2003格式不對 瀏覽:86
百度雲怎麼編輯文件在哪裡 瀏覽:304
起名app數據哪裡來的 瀏覽:888
微信怎麼去泡妞 瀏覽:52
百度廣告html代碼 瀏覽:244
qq瀏覽器轉換完成後的文件在哪裡 瀏覽:623
jsp中的session 瀏覽:621
壓縮完了文件去哪裡找 瀏覽:380
武裝突襲3浩方聯機版本 瀏覽:674
網路機頂盒移動網路 瀏覽:391
iphone手機百度雲怎麼保存到qq 瀏覽:148
資料庫設計與實踐讀後感 瀏覽:112
js對象是什麼 瀏覽:744
網頁文件存pdf 瀏覽:567
文件夾正裝 瀏覽:279
剛復制的文件找不到怎麼辦 瀏覽:724
試運行適用於哪些體系文件 瀏覽:987
ghost文件復制很慢 瀏覽:967
傑德原車導航升級 瀏覽:240
編程dest是什麼意思 瀏覽:935

友情鏈接