前言
在使用爬蟲爬取數(shù)據(jù)的時(shí)候,當(dāng)需要爬取的數(shù)據(jù)量比較大,且急需很快獲取到數(shù)據(jù)的時(shí)候,可以考慮將單線程的爬蟲寫成多線程的爬蟲。下面來(lái)學(xué)習(xí)一些它的基礎(chǔ)知識(shí)和代碼編寫方法。
一、進(jìn)程和線程
進(jìn)程可以理解為是正在運(yùn)行的程序的實(shí)例。進(jìn)程是擁有資源的獨(dú)立單位,而線程不是獨(dú)立的單位。由于每一次調(diào)度進(jìn)程的開銷比較大,為此才引入的線程。一個(gè)進(jìn)程可以擁有多個(gè)線程,一個(gè)進(jìn)程中可以同時(shí)存在多個(gè)線程,這些線程共享該進(jìn)程的資源,線程的切換消耗是很小的。因此在操作系統(tǒng)中引入進(jìn)程的目的是更好地使多道程序并發(fā)執(zhí)行,提高資源利用率和系統(tǒng)吞吐量;而引入線程的目的則是減小程序在并發(fā)執(zhí)行時(shí)所付出的時(shí)空開銷,提高操作系統(tǒng)的并發(fā)性能。
下面用簡(jiǎn)單的例子進(jìn)行描述,打開本地計(jì)算機(jī)的”任務(wù)管理器”如圖1所示,這些正在運(yùn)行的程序叫作進(jìn)程。如果將一個(gè)進(jìn)程比喻成一個(gè)工作,指定10個(gè)人來(lái)做這份工作,這10個(gè)人就是10個(gè)線程。因此,在一定的范圍內(nèi),多線程效率比單線程效率更高。
圖1.任務(wù)管理器
二、Python中的多線程與單線程
在我們平時(shí)學(xué)習(xí)的過(guò)程中,使用的主要是單線程爬蟲。一般來(lái)說(shuō),如果爬取的資源不是特別大,使用單線程即可。在Python中,默認(rèn)情況下是單線程的,簡(jiǎn)單理解為:代碼是按順序依次運(yùn)行的,比如先運(yùn)行第一行代碼,再運(yùn)行第二行,依次類推。在前面章節(jié)所學(xué)習(xí)知識(shí)中,都是以單線程的形式實(shí)踐的。
舉個(gè)例子,批量下載某網(wǎng)站的圖片,由于下載圖片是一個(gè)耗時(shí)的操作,如果依然采用單線程的方式下載,那么效率就會(huì)特別低,意味著需要消耗更多的時(shí)間等待下載。為了節(jié)約時(shí)間,這時(shí)候我們就可以考慮使用多線程的方式來(lái)下載圖片。
threading模塊是Python中專門用來(lái)做多線程編程的模塊,它對(duì)thread進(jìn)行了封裝,使用更加方便。例如需要對(duì)寫代碼和玩游戲兩個(gè)事件使用多線程進(jìn)行,案例代碼如下。
import threading
import time
# 定義第一個(gè)
def coding():
for x in range(3):
print('%s正在寫代碼\n' % x)
time.sleep(1)
# 定義第二個(gè)
def playing():
for x in range(3):
print('%s正在玩游戲\n' % x)
time.sleep(1)
# 如果使用多線程執(zhí)行
def multi_thread():
start = time.time()
# Thread創(chuàng)建第一個(gè)線程,target參數(shù)為函數(shù)命
t1 = threading.Thread(target=coding)
t1.start() # 啟動(dòng)線程
# 創(chuàng)建第二個(gè)線程
t2 = threading.Thread(target=playing)
t2.start()
# join是確保thread子線程執(zhí)行完畢后才能執(zhí)行下一個(gè)線程
t1.join()
t2.join()
end = time.time()
running_time = end - start
print('總共運(yùn)行時(shí)間 : %.5f 秒' % running_time)
# 執(zhí)行
if __name__ == '__main__':
multi_thread() # 執(zhí)行單線程
運(yùn)行結(jié)果如圖2所示:
圖2.多線程運(yùn)行結(jié)果
那么執(zhí)行單線程會(huì)消耗多少時(shí)間,案例代碼如下所示。
import time
# 定義第一個(gè)
def coding():
for x in range(3):
print('%s正在寫代碼\n' % x)
time.sleep(1)
# 定義第二個(gè)
def playing():
start = time.time()
for x in range(3):
print('%s正在玩游戲\n' % x)
time.sleep(1)
end = time.time()
running_time = end - start
print('總共運(yùn)行時(shí)間 : %.5f 秒' % running_time)
def single_thread():
coding()
playing()
# 執(zhí)行
if __name__ == '__main__':
single_thread() # 執(zhí)行單線程
運(yùn)行結(jié)果如圖3所示:
圖3.單線程運(yùn)行結(jié)果
經(jīng)過(guò)以上多線程和單線程的運(yùn)行結(jié)果,可以看出多線程中寫代碼和玩游戲是一起執(zhí)行的,單線程中則是先寫代碼再玩游戲。從時(shí)間上來(lái)說(shuō),可能只有細(xì)微的差距,當(dāng)執(zhí)行工作量很大的時(shí)候,便會(huì)發(fā)現(xiàn)多線程消耗的時(shí)間會(huì)更少,從這個(gè)案例中我們也可以知道,當(dāng)所需要執(zhí)行的任務(wù)并不多的時(shí)候,只需要編寫單線程即可。
三、單線程改為多線程
以某直播的圖片爬取為例,案例代碼如下:
import requests
from lxml import etree
import time
import os
dirpath = '圖片/'
if not os.path.exists(dirpath):
os.mkdir(dirpath) # 創(chuàng)建文件夾
header = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36'
}
def get_photo():
url = 'https://www.huya.com/g/4079/' # 目標(biāo)網(wǎng)站
response = requests.get(url=url, headers=header) # 發(fā)送請(qǐng)求
data = etree.HTML(response.text) # 轉(zhuǎn)化為html格式
return data
def jiexi():
data = get_photo()
image_url = data.xpath('//a//img//@data-original')
image_name = data.xpath('//a//img[@class="pic"]//@alt')
for ur, name in zip(image_url, image_name):
url = ur.replace('?imageview/4/0/w/338/h/190/blur/1', '')
title = name + '.jpg'
response = requests.get(url=url, headers=header) # 在此發(fā)送新的請(qǐng)求
with open(dirpath + title, 'wb') as f:
f.write(response.content)
print("下載成功" + name)
time.sleep(2)
if __name__ == '__main__':
jiexi()
如果需要修改為多線程爬蟲,只需要修改主函數(shù)即可,例如創(chuàng)建4個(gè)線程進(jìn)行爬取,案例代碼如下所示:
if __name__ == "__main__":
threads = []
start = time.time()
# 創(chuàng)建四個(gè)進(jìn)程
for i in range(1, 5):
thread = threading.Thread(target=jiexi(), args=(i,))
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
end = time.time()
running_time = end - start
print('總共消耗時(shí)間 : %.5f 秒' % running_time)
print("全部完成!") # 主程序
數(shù)據(jù)結(jié)構(gòu)與算法,是理論和實(shí)踐必須緊密結(jié)合的一門學(xué)科,有關(guān)數(shù)據(jù)結(jié)構(gòu)和算法同類的課程或書籍,有些只是名為“數(shù)據(jù)結(jié)構(gòu)”,而非“數(shù)據(jù)結(jié)構(gòu)與算法”,它們?cè)趦?nèi)容上并無(wú)很大區(qū)別。
實(shí)際上,數(shù)據(jù)結(jié)構(gòu)和算法,沒有必要也無(wú)法嚴(yán)格區(qū)分,兩者是“你中有我,我中有你”的關(guān)系?;蛘?,將數(shù)據(jù)結(jié)構(gòu)算做算法的一個(gè)分支也未嘗不可,比如著名教材《算法導(dǎo)論》,就包含大量數(shù)據(jù)結(jié)構(gòu)的內(nèi)容。本書中涉及的問(wèn)題,如果需要將數(shù)據(jù)以比較復(fù)雜的方式組織起來(lái),就歸類為數(shù)據(jù)結(jié)構(gòu);否則就歸類為算法。
目前,程序設(shè)計(jì)課程在中學(xué)已經(jīng)較為普及,在許多大中專院校更是理科生的必修課。社會(huì)上開辦編程培訓(xùn)班亦十分流行。許多沒有經(jīng)過(guò)系統(tǒng)的計(jì)算機(jī)專業(yè)學(xué)習(xí)的學(xué)生,經(jīng)過(guò)培訓(xùn)后若能掌握一兩門語(yǔ)言,學(xué)會(huì)一些前端后端應(yīng)用的開發(fā)技能,雖然這樣理論基礎(chǔ)薄弱,也能求得一份程序員的職位。
然而,要成為一名優(yōu)秀的程序員,有一門課程是沒有捷徑可以繞過(guò)去的,那就是“數(shù)據(jù)結(jié)構(gòu)與算法”。優(yōu)秀的公司是不會(huì)放心將重要的任務(wù)交給不懂?dāng)?shù)據(jù)結(jié)構(gòu)和算法的程序員的,因?yàn)槟切┏绦騿T沒有效率的觀念,一不小心就可能寫出肆意揮霍計(jì)算資源的程序,讓公司付出真金白銀的代價(jià)。比如,低效的后端將導(dǎo)致公司需要購(gòu)買更多的服務(wù)器才能提供服務(wù),甚至在訪問(wèn)量高時(shí)導(dǎo)致系統(tǒng)崩潰。如果有程序員信誓旦旦地說(shuō)他的工作不需要用到數(shù)據(jù)結(jié)構(gòu)和算法,那多半是因?yàn)樗乃讲蛔阋允顾佑|到需要數(shù)據(jù)結(jié)構(gòu)和算法的任務(wù)。
總之,計(jì)算機(jī)專業(yè)的人員需要掌握好數(shù)據(jù)結(jié)構(gòu)與算法,自不必說(shuō),非計(jì)算機(jī)專業(yè)的人員,不論打算轉(zhuǎn)行,還是已經(jīng)轉(zhuǎn)行做了程序員,都應(yīng)該學(xué)好這門課程。即便不做程序員,如果經(jīng)常需要用編程來(lái)解決工作中的問(wèn)題,學(xué)習(xí)這門課程也大有裨益。
1. A + B
題目
輸入兩個(gè)整數(shù),求這兩個(gè)整數(shù)的和是多少。
輸入格式
輸入兩個(gè)整數(shù)A,B
,用空格隔開
輸出格式
輸出一個(gè)整數(shù),表示這兩個(gè)數(shù)的和
數(shù)據(jù)范圍
0≤A,B≤108
樣例輸入:
3 4
樣例輸出:
7
AC代碼C:
#include <stdio.h>
int main()
{
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",a+b);
return 0;
}
2.棧
題目
棧是計(jì)算機(jī)中經(jīng)典的數(shù)據(jù)結(jié)構(gòu),簡(jiǎn)單的說(shuō),棧就是限制在一端進(jìn)行插入刪除操作的線性表。
棧有兩種最重要的操作,即 pop(從棧頂彈出一個(gè)元素)和 push(將一個(gè)元素進(jìn)棧)。
棧的重要性不言自明,任何一門數(shù)據(jù)結(jié)構(gòu)的課程都會(huì)介紹棧。
寧寧同學(xué)在復(fù)習(xí)棧的基本概念時(shí),想到了一個(gè)書上沒有講過(guò)的問(wèn)題,而他自己無(wú)法給出答案,所以需要你的幫忙。
寧寧考慮的是這樣一個(gè)問(wèn)題:一個(gè)操作數(shù)序列,從 1,2,一直到 n,棧 的深度大于 n。
現(xiàn)在可以進(jìn)行兩種操作,
將一個(gè)數(shù),從操作數(shù)序列的頭端移到棧的頭端(對(duì)應(yīng)數(shù)據(jù)結(jié)構(gòu)棧的 push
操作)。將一個(gè)數(shù),從棧的頭端移到輸出序列的尾端(對(duì)應(yīng)數(shù)據(jù)結(jié)構(gòu)棧的 pop
操作)。使用這兩種操作,由一個(gè)操作數(shù)序列就可以得到一系列的輸出序列。
你的程序?qū)?duì)給定的 n,計(jì)算并輸出由操作數(shù)序列 1,2,…,n經(jīng)過(guò)操作可能得到的輸出序列的總數(shù)。
輸入格式
輸入文件只含一個(gè)整數(shù) n
。
輸出格式
輸出文件只有一行,即可能輸出序列的總數(shù)目。
數(shù)據(jù)范圍
1≤n≤18
輸入樣例:
3
輸出樣例:
5
AC代碼C:
3.大小寫翻轉(zhuǎn)
AC代碼C:
#include<stdio.h> //包含頭文件stdio.h
#include<string.h> //包含頭文件string.h
int main() //程序從這里開始執(zhí)行
{
char a[100]; //定義一個(gè)字符數(shù)組a,長(zhǎng)度為100
int i=0; //定義整型變量i并初始化為0
gets(a); //輸入字符串,并存儲(chǔ)在a數(shù)組中
while(a[i]!='\0') //循環(huán)語(yǔ)句,判斷a數(shù)組中第i個(gè)元素是否為'\0'(即是否到了字符串結(jié)尾)
{
if(a[i]>='a'&&a[i]<='z') //如果a數(shù)組中第i個(gè)元素是小寫字母
{
a[i]=a[i]-32; //將其轉(zhuǎn)換為對(duì)應(yīng)的大寫字母
}else if(a[i]>='A'&&a[i]<='Z') //如果a數(shù)組中第i個(gè)元素是大寫字母
{
a[i]=a[i]+32; //將其轉(zhuǎn)換為對(duì)應(yīng)的小寫字母
}
i++; //i自增1
}
puts(a); //輸出轉(zhuǎn)換后的字符串
getchar(); //等待用戶輸入任何字符后結(jié)束程序
return 0; //程序正常結(jié)束
}
4.非素?cái)?shù)個(gè)數(shù)
求 [a,b]
之間的非素?cái)?shù)個(gè)數(shù)。
特別的,1 也算作素?cái)?shù)。
輸入格式
輸入包含多組測(cè)試數(shù)據(jù)。
每組數(shù)據(jù)占一行,包含兩個(gè)整數(shù) a,b
。
輸出格式
每組數(shù)據(jù)輸出一行答案,表示非素?cái)?shù)的個(gè)數(shù)。
數(shù)據(jù)范圍
1≤a≤b≤107
,
輸入最多包含 10組數(shù)據(jù)。
輸入樣例:
1 10
1 100
輸出樣例:
5
74
不完全AC代碼C:
完全的我不會(huì)寫,先留著吧,因?yàn)槲沂莻€(gè)lj
#include <stdio.h>
// 判斷一個(gè)數(shù)是否為素?cái)?shù),返回值為0或1
int hanshu1(int x)
{
for (int i = 2; i * i <= x; i++) // 枚舉小于等于sqrt(x)的所有數(shù)
{
if (x % i == 0) return 1; // 如果x能被i整除,說(shuō)明x不是素?cái)?shù),返回1
}
return 0; // 否則返回0,表示x是素?cái)?shù)
}
int main()
{
int a, b;
while (scanf("%d%d", &a, &b) != EOF) // 讀入多組數(shù)據(jù),直到讀取到文件結(jié)尾
{
int count = 0; // 統(tǒng)計(jì)[a,b]中的素?cái)?shù)個(gè)數(shù)
for (int i = a; i <= b; i++) // 枚舉區(qū)間[a,b]中的所有數(shù)
{
if (hanshu1(i)) count++; // 如果i是素?cái)?shù),計(jì)數(shù)器加1
}
printf("%d\n", count); // 輸出素?cái)?shù)個(gè)數(shù)
}
return 0;
}
該代碼主要使用了兩個(gè)函數(shù):hanshu1
和main
。hanshu1
函數(shù)用于判斷一個(gè)數(shù)是否為素?cái)?shù),main
函數(shù)用于讀入多組數(shù)據(jù),統(tǒng)計(jì)每組數(shù)據(jù)中區(qū)間[a,b]中的素?cái)?shù)個(gè)數(shù)。
在hanshu1
函數(shù)中,使用了一個(gè)循環(huán)來(lái)枚舉小于等于sqrt(x)的所有數(shù)i,并判斷x是否能被i整除。如果x能被i整除,說(shuō)明x不是素?cái)?shù),返回1;否則返回0,表示x是素?cái)?shù)。
在main
函數(shù)中,使用了一個(gè)循環(huán)來(lái)讀入多組數(shù)據(jù),并對(duì)每組數(shù)據(jù)進(jìn)行相同的操作。首先定義一個(gè)計(jì)數(shù)器count,用于統(tǒng)計(jì)區(qū)間[a,b]中的素?cái)?shù)個(gè)數(shù)。然后使用另一個(gè)循環(huán)來(lái)枚舉區(qū)間[a,b]中的所有數(shù)i,如果i是素?cái)?shù),計(jì)數(shù)器count加1。最后輸出計(jì)數(shù)器count的值,即為區(qū)間[a,b]中的素?cái)?shù)個(gè)數(shù)。
5.母牛的故事
題目描述
有一頭母牛,它每年年初生一頭小母牛。每頭小母牛從第四個(gè)年頭開始,每年年初也生一頭小母牛。請(qǐng)編程實(shí)現(xiàn)在第n年的時(shí)候,共有多少頭母牛?
輸入格式
輸入數(shù)據(jù)由多個(gè)測(cè)試實(shí)例組成,每個(gè)測(cè)試實(shí)例占一行,包括一個(gè)整數(shù)n(0<n<55),n的含義如題目中描述。
n=0表示輸入數(shù)據(jù)的結(jié)束,不做處理。
輸出格式
對(duì)于每個(gè)測(cè)試實(shí)例,輸出在第n年的時(shí)候母牛的數(shù)量。
每個(gè)輸出占一行。
樣例輸入
2
4
5
0
樣例輸出
2
4
6
AC代碼C:
#include <stdio.h>
// 遞歸函數(shù),計(jì)算斐波那契數(shù)列的第n項(xiàng),返回值為整數(shù)
int hanshu(int x)
{
if (x <= 4) return x; // 當(dāng)n<=4時(shí),直接返回n的值
else // 當(dāng)n>4時(shí),遞歸計(jì)算前兩項(xiàng)的和
return hanshu(x - 3) + hanshu(x - 1);
}
int main()
{
int a;
while (scanf("%d", &a)&&a) // 循環(huán)讀入多組數(shù)據(jù)
printf("%d\n", hanshu(a)); // 對(duì)每組數(shù)據(jù)進(jìn)行相同的操作,輸出斐波那契數(shù)列的第n項(xiàng)
return 0;
}
該代碼定義了一個(gè)遞歸函數(shù)hanshu
,用于計(jì)算斐波那契數(shù)列的第n項(xiàng)。在函數(shù)中,當(dāng)n<=4時(shí),直接返回n的值;當(dāng)n>4時(shí),遞歸計(jì)算前兩項(xiàng)的和。
該代碼還包括一個(gè)循環(huán)語(yǔ)句,用于讀入多組數(shù)據(jù),并對(duì)每組數(shù)據(jù)進(jìn)行相同的操作。使用scanf
函數(shù)從標(biāo)準(zhǔn)輸入中讀入一個(gè)整數(shù)a,并調(diào)用函數(shù)hanshu
計(jì)算斐波那契數(shù)列的第a項(xiàng)。最后使用printf
函數(shù)輸出計(jì)算結(jié)果。
6.用篩法求之N內(nèi)的素?cái)?shù)
AC代碼C:
#include<stdio.h>
int main()
{
int n;
scanf("%d",&n);
int i,j;
for(i=2;i<=n;i++)
{
for(j=2;j*j<=i;j++)
if(i%j==0) break;
if(j>sqrt(i)) printf("%d\n",i);
}
}
7.C語(yǔ)言訓(xùn)練-計(jì)算一個(gè)整數(shù)N的階乘
#include<stdio.h>
int main()
{
int a,t=1;
scanf("%d",&a);
for(int i = 1;i<=a;i++)
t*=i;
printf("%d",t);
return 0;
}
i++和++i的區(qū)別
1、首先,單獨(dú)拿出來(lái)說(shuō),i++和++i的意思是一樣的,就是i = i + 1。
2、如果當(dāng)做運(yùn)算符來(lái)說(shuō),就是a = i++ 和 a = ++i這樣的形式,情況就不一樣了。
a = i++的意思是,先把i的值賦給a,即a = i,再執(zhí)行i = i + 1;
a = ++i是先執(zhí)行 i = i+1,再把i的值賦給a;
舉個(gè)例子來(lái)說(shuō),如果一開始i=4。
那么執(zhí)行a=i++這條語(yǔ)句之后,a=4,i=5;
那么執(zhí)行a=++i這條語(yǔ)句之后,i=5,a=5;
同理,i–和–i的用法也是一樣的。
3、另外在循環(huán)體中的區(qū)別(重要)
①for循環(huán)中,for(int i = 0;i < 6;i++)和for(int i = 0;i < 6;++i)效果一樣
② while(i++)是先用i的初始化值做循環(huán)變量再i+1
而while(++i)是先用i的初始值+1,再循環(huán)
8.輸人兩個(gè)正整數(shù)m和n,求其最大公約數(shù)和最小公倍數(shù)
最大公約數(shù)和最小公倍數(shù)之間的性質(zhì):兩個(gè)自然數(shù)的乘積等于這兩個(gè)自然數(shù)的最大公約數(shù)和最小公倍數(shù)的乘積。
AC代碼C:
#include <stdio.h>
int main()
{
int p,r,m,n,temp;
printf("請(qǐng)輸入兩個(gè)正整數(shù)m,n:");
scanf("%d%d",&m,&n);
if(n<m)
{
temp=n;
n=m;
m=temp;
}
p=n*m;
while(m!=0)
{
r=n%m;
n=m;
m=r;
}
printf("最大公布數(shù):%d\n",n);
printf("最小公倍數(shù):%d\n",p/n);
}
9.輸人一行字符,分別統(tǒng)計(jì)出其中英文字母、空格、數(shù)字和其他字符的個(gè)數(shù)
AC代碼C:
這段代碼中的 while 循環(huán)是一個(gè)字符輸入循環(huán),其條件為 (cc=getchar())!='\n'
。
在每次循環(huán)中,getchar()
函數(shù)用于從輸入流中讀取一個(gè)字符,并將其賦值給變量 cc
。然后,條件表達(dá)式 (cc=getchar())!='\n'
檢查讀取的字符是否為換行符(\n
)。如果不是換行符,則循環(huán)繼續(xù)執(zhí)行;如果是換行符,則循環(huán)結(jié)束。
這樣的循環(huán)結(jié)構(gòu)可以用來(lái)逐個(gè)讀取用戶輸入的一行字符,直到遇到換行符為止。每次讀取一個(gè)字符后,根據(jù)字符的類型進(jìn)行相應(yīng)的統(tǒng)計(jì)操作,如統(tǒng)計(jì)英文字母數(shù)目、空格數(shù)目、數(shù)字?jǐn)?shù)目和其他字符數(shù)量。
#include<stdio.h>
int main()
{
char cc;
int a=0,b=0,c=0,d=0;
printf("請(qǐng)輸入一行字符:");
while((cc=getchar())!='\n')
{
if(cc>='a'&&cc<='z'||cc>='A'&&cc<='Z')
{
a++;
}
else if(cc == ' ')
{
b++;
}
else if(cc>='0'&&c<='9')
{
c++;
}
else
{
d++;
}
}
printf("英文字母數(shù)目是:%d\n 空格數(shù)目:%d\n 數(shù)字?jǐn)?shù)目:%d\n 其他字符數(shù)量:%d\n",a,b,c,d);
return 0;
}
10.求 S n S_n Sn?=a+aa+aaa+…+ a a + ? + a ? n 個(gè) a \overbrace{aa+\dots+a}^{n個(gè)a} aa+?+a ?n個(gè)a? 之值,其中a是一個(gè)數(shù)字,n表示a的位數(shù),a、n由鍵盤輸入
AC代碼C:
可以使用math.h頭文件中的pow函數(shù)來(lái)計(jì)算10的i次冪
#include<stdio.h>
#include<math.h>
int main()
{
int n;
double a,sum,totle_sum;
printf("輸入a的值以及n的值");
scanf("%lf %d",&a,&n);
for(int i=0;i<n;i++)
{
sum+=a*pow(10,i);
totle_sum+=sum;
}
printf("總和是:%lf\n",totle_sum);
}
11.求 ∑ n = 1 20 n ! \sum\limits_{n=1}^{20}n! n=1∑20?n! (即求1!+2!+3!+4!+…+20!)
在C語(yǔ)言標(biāo)準(zhǔn)中,?double?類型的取值范圍通常是-1.7E308到1.7E308之間,而 ?int?類型的取值范圍通常是-32768到32767之間(這些范圍可能會(huì)因?yàn)椴煌木幾g器或平臺(tái)而有所不同)。因此,如果需要處理比較大的數(shù)值,使用 ?double?類型可以更好地滿足需求。
AC代碼C:
#include<stdio.h>
int main()
{
double sum=0;
for(int i=0;i<=20;i++)
{
double single_sum = 1;
for(int j = i;j>0;j--)
{
single_sum*=j;
}
sum+=single_sum;
}
printf("階乘和為:%lf\n",sum);
}
12.求和 ∑ k = 1 100 k \sum\limits{k=1}^{100}k ∑k=1100k + ∑ k = 1 50 k 2 \sum\limits{k=1}^{50}{k}^2 ∑k=150k2+ ∑ k = 1 10 1 k \sum\limits_{k=1}^{10}{\frac{1}{k}} k=1∑10?k1?
1.0/k表示1.0除以k,其中1.0是一個(gè)浮點(diǎn)數(shù)常量,而k可以是整數(shù)或浮點(diǎn)數(shù)。結(jié)果將會(huì)是一個(gè)浮點(diǎn)數(shù),即使k是整數(shù)類型。
1/k表示整數(shù)除法,其中k必須是整數(shù)類型。如果k是整數(shù)類型,那么1/k將會(huì)進(jìn)行整數(shù)除法運(yùn)算,結(jié)果將會(huì)是整數(shù)類型。在整數(shù)除法中,會(huì)將小數(shù)部分舍去,只保留整數(shù)部分。
AC代碼C:
#include<stdio.h>
int main()
{
double sum=0,sum1=0,sum2=0,sum3=0;
for(int k=1;k<=100;k++)
{
sum1+=k;
if(k<=50)
{
sum2+=k*k;
}
if(k<=10)
{
sum3+=1.0/k;
}
}
sum=sum1+sum2+sum3;
printf("三種情況求和結(jié)果:%lf\n",sum);
}
13.輸出所有的“水仙花數(shù)”,所謂“水仙花數(shù)”是指一個(gè)3位數(shù),其各位數(shù)字立方和等于該數(shù)本身。
如果操作數(shù)都是整數(shù)類型,則執(zhí)行整數(shù)除法。整數(shù)除法將返回一個(gè)整數(shù)值,省略小數(shù)部分,只保留整數(shù)部分。例如,?5 / 2?將返回2,而不是2.5。
如果操作數(shù)中至少有一個(gè)是浮點(diǎn)數(shù)類型,則執(zhí)行浮點(diǎn)數(shù)除法。浮點(diǎn)數(shù)除法將返回一個(gè)浮點(diǎn)數(shù)值,保留小數(shù)部分。例如,?5.0 / 2?將返回2.5。
AC代碼C:
#include<stdio.h>
int main()
{
int a,b,c;
for(int i=100;i<=999;i++)
{
a=i/100;
b=(i/10)%10;
c=i%10;
if(a*a*a+b*b*b+c*c*c==i)
{
printf("%d\n",i);
}
}
}
14.一個(gè)數(shù)如果恰好等于它的因子之和,這個(gè)數(shù)就稱為“完數(shù)”。
例如,6的因子為1,2,3,而6=1+2+3,因此6是“完數(shù)”。編程序找出1000之內(nèi)的所有完數(shù),并按下面格式輸出其因子:
6 its factors are 1,2,3
AC代碼C:
#include<stdio.h>
int main()
{
int a,factor,sum;
for(a=2;a<=1000;a++)
{
sum =1;
for(factor=2;factor<=a/2;factor++)
{
if(a%factor==0)
{
sum+=factor;
}
}
if(sum==a)
{
printf("%d因子是:1,",a);
for(factor=2;factor<=a/2;factor++)
{
if(a%factor==0)
{
printf("%d,",factor);
}
}
printf("\n");
}
}
}
15.有一個(gè)分?jǐn)?shù)序列,求出這個(gè)數(shù)列的前20項(xiàng)之和。
2 1 \frac{2}{1} 12?, 3 2 \frac{3}{2} 23?, 5 3 \frac{5}{3} 35?, 8 5 \frac{8}{5} 58?, 13 8 \frac{13}{8} 813?, 25 13 \frac{25}{13} 1325?,…
AC代碼C:
#include<stdio.h>
int main()
{
double a=2,b=1,sum=0;
double temp;
int count;
scanf("%d",&count);
for(int i=0;i<count;i++)
{
sum+=a/b;
temp=a;
a=a+b;
b=temp;
}
printf("前%d項(xiàng)之和:%lf\n",count,sum);
}
16.一個(gè)球從100m高度自由落下,每次落地后反彈回原高度的一半,再落下,再反彈。
求它在第10次落地時(shí)共經(jīng)過(guò)多少米,第10次反彈多高。
不需要計(jì)算第10次的反彈高度,所以減去文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-647337.html
AC代碼C:
#include<stdio.h>
int main()
{
double a=100;
double sum=0;
for(int i=0;i<10;i++)
{
sum+=a;
a=a/2;
sum+=a;
}
sum=sum-a;
printf("小球供經(jīng)歷%lf米,第10次反彈%lf米\n",sum,a);
return 0;
}
17.猴子吃桃問(wèn)題。
猴子第1天摘下若干個(gè)桃子,當(dāng)即吃了一半,還不過(guò)癮,又多吃了一個(gè)。第2天早上又將剩下的桃子吃掉一半,又多吃了一個(gè)。以后每天早上都吃了前一天剩下的一半零一個(gè)。到第10天早上想再吃時(shí),就只剩一個(gè)桃子了。求第1天共摘多少個(gè)桃子。
前一天的桃子數(shù)量 = (后一天桃子數(shù)量+1) * 2文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-647337.html
AC代碼C:
#include<stdio.h>
int main()
{
int day=9;
int day_count;
int count=1;
while(day>0)
{
day_count=(count+1)*2;
count = day_count;
day--;
}
printf("total count:%d\n",count);
return 0;
}
18.有一個(gè)已經(jīng)排好序的數(shù)組,要求輸入一個(gè)數(shù)后,按原來(lái)順序的規(guī)律將它插入數(shù)組中
AC代碼C:
#include<stdio.h>
int main()
{
int num;
int shuzu[10]={1,2,3,4,5,6,7,8,9,10};
printf("請(qǐng)輸入一個(gè)整數(shù):");
scanf("%d",&num);
printf("%d\n",num);
int end=9;
while(end>=0&&num<shuzu[end])
{
shuzu[end+1]=shuzu[end];
end--;
}
shuzu[end+1]=num;
for(int i=0;i<11;i++)
{
printf("%d\n",shuzu[i]);
}
printf("\n");
}
到了這里,關(guān)于Python爬蟲:?jiǎn)尉€程、多線程、多進(jìn)程的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!