前段时间参加一个公司的笔试,其中一个题目是实现税前工资和税后工资的相应转化(由税前求税后、由税后求税前)。题目介绍如下:
下表是2011年9月1日起调整后现行的7级超额累进税率(原题目中没有最后一列)
全月应纳税所得额 |
税率 |
速算扣除数(元) |
全月应纳税额不超过1500元 |
3% |
0 |
全月应纳税额超过1500元至4500元 |
10% |
105 |
全月应纳税额超过4500元至9000元 |
20% |
555 |
全月应纳税额超过9000元至35000元 |
25% |
1005 |
全月应纳税额超过35000元至55000元 |
30% |
2755 |
全月应纳税额超过55000元至80000元 |
35% |
5505 |
全月应纳税额超过80000元 |
45% |
13505 |
这里的税前工资是指:扣除五险一金后的工资;应纳税所得额是税前工资超过税起征点(3500元)的工资;税后工资是税前工资去除个人所得税后的工资。
1.税前工资求解税后工资
按照上表中个人所得税税率,首先分段求得个人所得税,然后税前工资减去税收即得税后工资。
例如:税前工资为10000,应纳税所得额为10000-3500=6500,个人所得税落在三段内,为1500×3%+(4500-1500)×10%+(6500-4500)×20%=745。税后工资为10000-745=9255。
float function(float wage) { float taxable = wage - 3500; float tax = 0.0; if (taxable > 0 && taxable <= 1500) { tax = taxable * 0.03; } else if(taxable > 1500 && taxable<= 4500) { tax = (taxable -1500)*0.1 + 1500 * 0.03; } else if(taxable > 4500 && taxable<= 9000) { tax = (taxable -4500)*0.2 + 1500 *0.03 + 3000 *0.1; } else if(taxable > 9000 && taxable<= 35000) { tax = (taxable -9000)*0.25 + 1500 *0.03 + 3000 *0.1 + 4500*0.2; } else if(taxable > 35000 && taxable <= 55000) { tax = (taxable -35000)*0.3 + 1500 *0.03 + 3000 *0.1 + 4500*0.2 + 26000 *0.25; } else if(taxable > 55000 && taxable <= 80000) { tax = (taxable -55000)*0.35 + 1500 *0.03 + 3000 *0.1 + 4500*0.2 + 26000 *0.25 + 25000* 0.3; } else if(taxable > 80000) { tax = (taxable -80000)*0.45 + 1500 *0.03 + 3000 *0.1 + 4500*0.2 + 26000 *0.25 + 25000* 0.3 + 25000 * 0.35; } return wage - tax; }
程序比较简单,面试官看后说这程序谁都会写,不是我想要的。当时就凌乱了,回来看了查了很多博客,到现在也没有很好的实现方法。下面介绍下实际中计算税后工资的方法,这种方式也只是在计算上简单些,程序实现和上面的方法基本相同。
为了便于计算,引入了速算扣除数的概念。速算扣除数的计算公式是:
本级速算扣除额=上一级最高所得额×(本级税率-上一级税率)+上一级速算扣除数
例如:如某人工资扣除3500元后的应纳税所得额是2200元,则税款计算方法为:1500×3%+700×10%=115元。个人所得税的计算,也可以将应纳税所得额直接按对应的税率来速算,但要扣除一个速算扣除数,否则会多计算税款。
如某人工资扣除3500元后的应纳税所得额是2200元,2200元对应的税率是10%,则税款速算方法为:2200*10%-105=115元。这里的105就是速算扣除数,因为2200元中,有1500元多计算了7%的税款,需要减去。其它金额的速算扣除数,如表格中最后一列所示。
/* *作者:侯凯 *说明:北京:求税后工资 *日期:2013-10-19 */ float function2(float wage) { float taxable = wage - 3500;//3500征税起点 float tax = 0; if(01500) { tax = taxable*0.03; } else if(taxable>1500&&taxable<=4500) { tax = taxable*0.1 - 105; } else if(taxable>4500&&taxable<=9000) { tax = taxable*0.2 - 555; } else if(taxable>9000&&taxable<=35000) { tax = taxable*0.25 - 1005; } else if(taxable>35000&&taxable<=55000) { tax = taxable*0.3 - 2755; } else if(taxable>55000&&taxable<=80000) { tax = taxable*0.35 - 5505; } else if(taxable>80000) { tax = taxable*0.45 - 13505; } return wage - tax; }
程序实现也比较简单,这样做就需要首先计算出各段的速算扣除数。其它更好的实现方法,目前没有找到,大家有什么好的思路,希望不吝指教。
2.税后工资反推税前工资
引入速算扣除数后,设税前工资所处的金额段税率为taxrate,对应金额段的速算数为quicknum,知:
求解思路:首先根据金额段A的税率和速算数,由税后计算得税前工资,判断如果税前工资落在金额段A内,返回即可,否则继续执行。
float after2wage(float taxwage) { float hold = 3500; float wage; //第一段 wage = taxwage; if(wagereturn wage;} //第二段 wage = (taxwage-3500*0.03)/(1-0.03); if(wage>hold&&wage<=hold+1500){return wage;} //第三段 wage = (taxwage-105-3500*0.1)/(1-0.1); if(wage>hold+1500&&wage<=hold+4500){return wage;} //第四段 wage = (taxwage-555-3500*0.2)/(1-0.2); if(wage>hold+4500&&wage<=hold+9000){return wage;} //第五段 wage = (taxwage-1005-3500*0.25)/(1-0.25); if(wage>hold+9000&&wage<=hold+35000){return wage;} //第六段 wage = (taxwage-2755-3500*0.3)/(1-0.3); if(wage>hold+35000&&wage<=hold+55000){return wage;} //第七段 wage = (taxwage-5505-3500*0.35)/(1-0.35); if(wage>hold+55000&&wage<=hold+80000){return wage;} //第八段 wage = (taxwage-13505-3500*0.45)/(1-0.1); if(wage>hold+80000){return wage;} }
3.C++中IO的格式控制
3.1使用控制符控制输出格式,需要包含头文件iomanip
控制符 |
作用 |
dec |
设置整数的基数为10 |
hex |
设置整数的基数为16 |
oct |
设置整数的基数为8 |
setbase(n) |
设置整数的基数为n(n只能是16,10,8之一) |
setfill(c) |
设置填充字符c,c可以是字符常量或字符变量 |
setprecision(n) |
设置实数的精度为n位。在以fixed(固定小数位 数)形式和scientific(指数)形式输出时,n为小数位数。 |
setw(n) |
设置字段宽度为n位。 |
setiosflags(ios::fixed) |
设置浮点数以固定的小数位数显示。 |
setiosflags(ios::scientific) |
设置浮点数以科学计数法(即指数形式)显示。 |
setiosflags(ios::left) |
输出数据左对齐。 |
setiosflags(ios::right) |
输出数据右对齐。 |
setiosflags(ios::skipws) |
忽略前导的空格。 |
setiosflags(ios::uppercase) |
在以科学计数法输出E和十六进制输出字母X时,以大写表示。 |
setiosflags(ios::showpos) |
输出正数时,给出“+”号。 |
resetiosflags |
终止已设置的输出格式状态,在括号中应指定内容。 |
ios为设置格式状态的格式标志,还包含其他一些。
3.2用流对象的成员控制输出格式,只需要iostream即可
流成员函数 |
与之作用相同的控制符 |
作用 |
precision(n) |
setprecision(n) |
设置实 数的精度为n位。 |
width(n) |
setw(n) |
设置字段宽度为n位。 |
fill(c) |
setfill(c) |
设置填充字符c。 |
setf( ) |
setiosflags( ) |
设置输出格式状态,括号中应给出格式状态,内容与控制符setiosflags括号中内容相同。 |
unsetf( ) |
resetiosflags( ) |
终止已设置的输出格式状态。 |
流成员函数基本可以实现控制符的全部功能。简单示例
/* *作者:侯凯 *说明:cout格式控制 *日期:2013-10-19 */ #includeusing namespace std; int main() { cout.width(2); cout.fill('0'); cout.setf(ios::left); cout<<1< //10 system("Pause"); }