《程式設計珠璣》學習記錄第三章資料決定程式的結構

2021-10-09 09:33:43 字數 4420 閱讀 3416

這章講的是資料結構對程式的影響:

使得程式**簡潔、已讀。畢竟程式是給人看的,所以能被人看懂,才是**的首要任務。

提高效率。不僅是**的執行效率,還有**的維護效率。

習題1:稅收問題。題目中使用if-else的分支語句的缺點有兩點:

**太長,需要大概500行**左右才能完成功能,也不利於之後的**更新。

**從上到下執行,是乙個順序查詢的過程,效率太低。

問題分析:分段的稅收問題。這個問題可以有兩種方法進行處理:

遞推公式法。很容易就可以得到分段稅收的遞推公式,但是對於一次稅收結果的計算時間複雜度太高。稅收計算可能是需要進行大規模計算的,所以遞推公式法並不適應於現實情況。

陣列分階段查詢法。對於每乙個階段可以用公式表示:本階段基礎稅 + 本階段稅率 * (income - 本階段基礎收人),其實這與題目中的if-else分支方法中的做法一樣。現在需要有兩個陣列來記錄 「本階段基礎稅」 和「本階段基礎收入」,對於「本階段稅率」可以由陣列的下標計算出來。接下來的問題就對陣列的查詢,對於這個問題可以使用兩個方法:二分查詢、標示法(取餘)。**如下:

#include using namespace std;

#define minicome 2200 //最低徵稅收入

#define maxicome 102200 //階段收稅的最大收入,大於此收入的按照統一標準

#define icomespan 500 //階段稅收的跨度

#define minrate 0.14 //最低稅率

#define ratespan 0.01 //稅率的跨度

double incomearray[(maxicome - minicome) / icomespan + 1]; //階段收入陣列

double basetaxarray[(maxicome - minicome) / icomespan + 1];//階段稅陣列

//使用二分查詢計算稅

double calculatetax(double income)

else if(income >= maxicome)

//使用二分查詢,找到income所處的階段, incomearray[i] <= income < incomearray[i+1]

//二分查詢的區間[ start, end ), 左閉右開。

int start = 0;

int end = (maxicome - minicome) / icomespan;

while(!(incomearray[start] <= income && income < incomearray[start+1]))

else

} return basetaxarray[start] + (minrate + ratespan * start) * (income - incomearray[start]);

}//使用標註法

double calculatetax2(double income)

else if(income >= maxicome)

int index = (int)((income - minicome) / icomespan);//確定階段所對應的索引

return basetaxarray[index] + (minrate + ratespan * index) * (income - incomearray[index]);

}int main()

else }

cout << calculatetax(3800) << endl;

cout << calculatetax2(3800) << endl;

}

習題4:解決日期問題。給定兩個日期計算兩者之間的天數;給定乙個日期,返回是週幾;給定年和月,生成該月日曆;**如下:

#include #include #include #include using namespace std;

/*date用來表示年月日*/

struct date

bool operator< (date& newdate)

};/*

sumdaysofmonth中第i項表示第i+1月1日到1月1日的天數累加和。

這裡只是初始值,下面的for迴圈會計算累加和。

*/ unsigned int sumdaysofmonth[12] = ;

/*判斷year是否為閏年, 如果是閏年返回true*/

bool isornotleapyear(unsigned int year)

/*計算earlierdate和laterdate之間的天數*/

unsigned int daysbetweendates(date earlierdate, date laterdate)

/* daystoearlieryear:表示日期 earlierdate到 earlierdate.year年1月1日的天數

daystolateryear:表示日期 laterdate 到 laterdate.year年1月1日的天數

daysbetweenearlierandlateryear:表示 earlierdate.year年1月1日 到 laterdate.year年1月1日的天數

daysbetweendates = daystolateryear + daysbetweenearlierandlateryear - daystoearlieryear;

*/ unsigned int daysbetweendates = 0;

unsigned int daystoearlieryear = 0;

unsigned int daystolateryear = 0;

unsigned int daysbetweenearlierandlateryear = 0;

daystoearlieryear = earlierdate.month > 1 ?

sumdaysofmonth[earlierdate.month - 2] + earlierdate.day :

earlierdate.day;

if(isornotleapyear(earlierdate.year) && earlierdate.month > 2) daystoearlieryear++;

daystolateryear = laterdate.month > 1 ?

sumdaysofmonth[laterdate.month - 2] + laterdate.day :

earlierdate.day;

if(isornotleapyear(laterdate.year) && laterdate.month > 2) daystolateryear++;

unsigned int currentyear = earlierdate.year;

while(currentyear < laterdate.year)

else

currentyear++; }

daysbetweendates = daystolateryear + daysbetweenearlierandlateryear - daystoearlieryear;

return daysbetweendates; }/*

weekday:計算date是星期幾。

一般日曆都是以2023年1月1日,星期1,作為基準日期

*/unsigned int weekday(date& date)

void showmonth(unsigned int year, unsigned int month);

if(isornotleapyear(year)) daysofmonth[1]++;

unsigned int weekday = weekday(date);

cout << weekday << endl;

unsigned int day = 1;

while(day <= daysofmonth[month - 1])

for(int i = 0; i < calendarformonth.size(); i++)

cout << endl; }}

int main()

date date1(2018, 8, 8);

date date2(2020, 8, 8);

date date3(2020, 9, 12);

cout << daysbetweendates(date1, date2) << endl;

cout << weekday(date3) << endl;

showmonth(2020, 10);

return 0;

}

結果:

程式設計珠璣第三章

第三章寫的有點太簡單了,可能作者是想在後面章節裡再詳細說吧!這一章就是作者說的幾句話印象還是很深刻。程式設計師在節省空間方面無計可施時,將自己從 中解脫出來,退回起點並記者並集 中精力研究資料,常常能有奇效。資料的 表示形式是程式設計的根本。正如人月神話的作者說 只要給我你設計的表,我就對你的程式一...

程式設計珠璣第三章習題1

問題 1.本書行將出版之時,美國的個人所得稅分為5種不同的費率,其中最大的費率大約為40 以前的情況更為複雜,稅率也更高。下面所示的程式文字採用25個if語句的合理方式來計算1978年的美國聯邦所得稅。稅率分別為0.14,0.15,0.16,0.17,0.18,此後的費率增幅大於0.01.有何建議?...

程式設計珠璣之第三章習題3

問題描述 3.編寫乙個 banner 函式,該函式的輸入為大寫字母,輸出為乙個字元陣列,該陣列以圖形化的方式表示該字母。問題解析 1 如果編寫乙個通用的以26個字母為引數,輸出為該字母的圖形化表示,我目前還沒有有效的方法,不過這對單個的字母,就簡單的多,這也是目前想到的解決該問題的方法,就是在該函式...