开篇
今天的问题来自于《编程珠玑》第三章【数据决定程序结构】,这里提出了几条代码优化相关的原则,受益不浅。下面是提到的几条原则:
- 使用数组重新编写重复代码。冗长的相似代码往往可以使用最简单的数据结构——数组来更好的表述;
- 封装复杂结构,当需要非常复杂的数据结构式,使用抽象术语来进行定义,并将操作表示为类;
- 尽可能使用高级工具。超文本、名字——值对、电子表格、数据库、编程语言等都是特定稳定领域中强大的工具。
- 从数据得出程序的结构。通过使用恰当的数据结构来代替复杂的代码,从数据可以得出程序的结构。万变不离其宗:在动手编写代码之前,优秀的程序员会彻底理解输入、输出和中间数据结构,并围绕这些结构创建程序。
问题概要
本书行将出版之时,美国的个人所得税分为5种不同的费率,其中最大的费率大约为40%。以前的情况更为复杂,税率也更高。下面所示的程序文本采用25个if语句的合理方式来计算1978年的美国联邦所得税。税率分别为0.14,0.15,0.16, 0.17, 0.18,·····。此后的费率增幅大于0.01.有何建议?(下面是书中的代码)
if income <= 2200tax = 0
else if income < 2700tax = . 14 * (income - 2200)
else if income <= 3200tax = 70 + . 15 * (income - 2700)
else if income <= 3700tax = 145 + . 16 * (income - 2200)
else if income <= 4200tax = 225 + . 17 * (income - 2200)
.....
else tax = 53090 + . 70 * (income - 102200)
思路分析
只看上面的代码,肯定是过于累赘了,虽然也能实现功能,但不仅不够优雅,而且也不方便维护。
比较理想的一种方法是把所有收入对应的阈值和税率都写在一个表格里,然后使用程序读取表格,不过这个应该是属于后面可能会写的拓展程序(到时单独发一篇文章)。要在上面的程序基础上进行优化,就可以使用一个数组来保存收入阈值和对应的 税率(第一条原则),然后封装出对应的方法。
下面的代码实现逻辑没什么复杂的,此处不多说,不过有一点值得注意的是税率的具体计算方式,比如说收入为3500, 则税值tax = 145 + 0.16 * (3500 - 3200)= 193,理解了这个计算方式,再去看我的代码,应该很容易理解了。
代码实现
#include<stdio.h>typedef struct {int threshold;// 收入阈值double rate;// 税率int baseTax;// 达到前一阈值的基础税额
} TaxBracket;// 计算税值
int calculate_tax(int income) {TaxBracket taxBracket[] = {{2200, 0.00, 0},{2700, 0.14, 0},{3200, 0.15, 70},{3700, 0.16, 145},{4200, 0.17, 225},};int numBracket = sizeof(taxBracket) / sizeof(taxBracket[0]);int tax = 0;int nextLimit = 0;if (income < taxBracket[0].threshold) {return 0;}for (int i = 0; i < numBracket - 1; i++) {if (income <= taxBracket[i + 1].threshold) {tax = taxBracket[i + 1].baseTax + (income - taxBracket[i].threshold) * taxBracket[i + 1].rate;return tax;}}// 若收入大于最后的阈值tax = taxBracket[numBracket - 1].baseTax + (income - taxBracket[numBracket - 1].threshold) * taxBracket[numBracket - 1].rate;return tax;
}int main() {int income;printf("请输入收入值: ");scanf_s("%d", &income);int tax = calculate_tax(income);printf("收入%d的应缴税额为%d\n", income, tax);return 0;
}
注
以上便是对于税率计算代码的一种优化实践方式,不过值得一提的是,我的代码肯定不算最优化的方式,只不过我技止于此,暂且没找到更加优化的方法,若各位大佬有什么想法,还请不吝指教了。
感谢阅读。