根据给定的工资计算要缴纳的所得税

Compute for the income tax to be paid based on the given salary

提问人:shampeyndadi 提问时间:11/16/2023 最后编辑:shampeyndadi 更新时间:11/17/2023 访问量:75

问:

编写一个程序,询问员工的工资,并根据给定的工资计算要支付的所得税。使用以下方案进行税款计算:

前 2 比索为 1000% 接下来的 7 比索为 2000% 剩余价值为11%

#include <stdio.h>

int main()
{
    float salary, incometax;

    printf("Enter salary: ");
    scanf("%f", &salary);

    if (salary <= 1000)
    {
       incometax = salary * 0.02;
       printf("Income tax to be paid: %.2f\n", incometax);
    }
     else if (salary <= 2000)
    {
       incometax = salary * 0.07;
       printf("Income tax to be paid: %.2f\n", incometax);
    }
    else if (salary > 2000)
    {
       incometax = salary * 0.11;
       printf("Income tax to be paid: %.2f\n", incometax);
    }

   return 0;
}

我不知道我所做的是否正确

更新

#include <stdio.h>

int main()
{
    float salary, incometax;

    printf("Enter salary: ");
    scanf("%f", &salary);

    if (salary <= 1000)
    {
        incometax = salary * 0.02;
        printf("Income tax to be paid: %.2f Pesos\n", incometax);
    }
    else if (salary < 3000)
    {
        incometax = (salary - 1000) * 0.07 + (1000 * 0.2);
        printf("Income tax to be paid: %.2f Pesos\n", incometax);
    }
    else 
    {
        incometax = ((salary - 3000) * 0.11) + 2000 * 0.07 + 1000 * 0.02;
        printf("Income tax to be paid: %.2f Pesos\n", incometax);
    }

    return 0;
}

我相信它是这样的。不过,如果我的条件是正确的,我不会。请检查。韦尔普

c

评论

1赞 Allan Wind 11/16/2023
好吧,您应该告诉我们问题出在哪里,例如实际输出和预期输出。例如,4000比索的税应该是多少?我不认为你的问题是税收规则的正确翻译。
2赞 Allan Wind 11/16/2023
货币通常是固定点,但如果要使用浮点类型,则更喜欢双倍而不是浮点。
0赞 Lundin 11/16/2023
请注意,在同一表达式中混合整数常量和浮点常量是一个非常糟糕的主意。您还使用了变量但常量,这没有意义。最有可能的是,你应该只使用,并在任何地方格式化(无论如何,这就是你在 PC 上编程 C 的方式)。floatdoubledouble%lf0.0
0赞 Allan Wind 11/16/2023
@Lundin 为什么混合整数和浮点常量是个坏主意?我想不出自动类型转换在这里有任何不良影响。
0赞 Lundin 11/16/2023
@AllanWind 在发布的代码中,有许多隐式升级,然后隐式转换回 ,这会带来精度损失。我们不应该允许隐性促销随心所欲地发生——好的代码根本不包含任何内容。此外,还有经典的新手错误,例如 或 .float5/2 + 0.5double x = 5/2;

答:

1赞 Allan Wind 11/16/2023 #1

不,您的计划没有正确实施边际税规则。例如,工资为 4000 比索,您的计划说所得税是 0.11 * 4000 = 440,但应该是 0.02 * 1000 + 0.07 * 2000 + 0.11 * 1000 = 270。

下面是一个实现:

#include <stdio.h>

double incometax(double salary) {
    double incometax = 0;
    if(salary < 0)
        incometax += 0;
    else if(salary <= 1000)
        incometax += 0.02 * (salary - 0);
    else
        incometax += 0.02 * (  1000 - 0);

    if(salary < 1000)
        incometax += 0;
    else if(salary <= 3000)
        incometax += 0.07 * (salary - 1000);
    else
        incometax += 0.07 * (  3000 - 1000);

    if(salary < 3000)
        incometax += 0;
    else
        incometax += 0.11 * (salary - 3000);
    return incometax;
}

int main(void) {
    double salary;
    printf("Enter salary: ");
    scanf("%lf", &salary);
    printf("Income tax to be paid: %.2lf\n", incometax(salary));
}

或更简洁地与三级运营商():?:

double incometax(double salary) {
    return
        0.02 * (salary <=    0 ? 0 : (salary <= 1000) ? salary -    0 : 1000 -    0) +
        0.07 * (salary <= 1000 ? 0 : (salary <= 3000) ? salary - 1000 : 3000 - 1000) +
        0.11 * (salary <= 3000 ? 0 : salary - 3000);
}

税收规则可能会发生变化,因此最好将其表示为数据(可能从文件、数据库或网站等外部来源读取)。在研究上述两个解决方案时,您可能还注意到,它们对 3 条规则中的每一条都重复了相同的内容。这意味着使用循环。最后,观察到规则的最高边际工资与规则的最低边际工资相同:ii+1

#include <values.h> // MAXDOUBLE

double incometax(double salary) {
    static const struct {
        double min;
        double rate;
    } rules[] = {
        {0, 0.02},
        {1000, 0.07},
        {3000, 0.11},
        {MAXDOUBLE, 0}
    };
    const size_t n = sizeof rules / sizeof *rules;
    double incometax = 0;
    for(size_t i = 0; i < n - 1; i++)
        incometax += rules[i].rate * (
            salary <= rules[i].min ? 0 :
            salary <= rules[i+1].min ? salary - rules[i].min :
            rules[i+1].min - rules[i].min
        );
    return incometax;
}

评论

0赞 Allan Wind 11/16/2023
别客气。如果这回答了您的问题,请单击它旁边的复选标记来接受它。
0赞 Peter - Reinstate Monica 11/17/2023 #2

这是一个精心设计的程序,具有以下功能:

  • 接受最高约 1.8 * 1013 个单位(卢比、美元等)的收入。
  • 精确计算美分。
  • 接受来自命令行或 stdin 的数据。
  • 当 stdin 为终端时提示。
  • 处理输入错误。
  • 即使在终端上,也可以简单地粘贴多个分隔的数字, 无需每行一个(下面的第 6 个输入提示)。

也许除了实际算法之外,还有一些东西在这里很有用:

  • 使用可以传达错误的返回类型 ()。struct ParseResult
  • 使用 和其他输入函数的返回值来检测输入错误,并将其与文件末尾区分开来。scanf
  • 将外观相似的代码移动到参数化函数中,而不是复制它(使和都小)。MakeParseResult()ParseIncomeInHundredthsFromString()ParseIncomeInHundredthsFromStream()
  • 有些算法非常适合递归,比如这个算法 ()。computeTaxes()
  • 将输入与处理分开(对 I/O 一无所知)。computeTaxes()
  • 就像 Allan 的回答一样,不要在代码中硬连接数据(数组可以从某个地方读取)。taxSteps
  • 注意取值范围(32 位对于高收入来说是不够的,更不用说美分或卢比了)。
  • 在 和 中使用正确的转换说明符,此处为: 和 。这有点麻烦,但对于便携性是必要的。不同的实现对 typedef 具有不同的本机数据类型,因此需要不同的转换说明符(例如,Linux 上的转换说明符就是 Windows 上的转换说明符)。printf()scanf()PRIu64SCNu64uint.._t%ul%ull
  • 尽管它不是标准的 C,但一些常见的 Posix 函数(如在非 Posix 实现中)也可用。它们很有用。isatty()

示例会话:

$ gcc -Wall -o income-tax income-tax.c && ./income-tax.exe
Tax brackets:
0.00 .. 1000.00: 2.00%
1000.00 .. 3000.00: 7.00%
Above: 11.00%
Please input income values in a format like '12345.99 ...'
1000.00
Taxes for 1000.00: 20.00
Please input income values in a format like '12345.99 ...'
3000.00
Taxes for 3000.00: 160.00
Please input income values in a format like '12345.99 ...'
10000.00
Taxes for 10000.00: 930.00
Please input income values in a format like '12345.99 ...'
10000.10
Taxes for 10000.10: 930.01
Please input income values in a format like '12345.99 ...'
1234.56 7890.89 121212121212.12
Taxes for 1234.56: 36.41
Please input income values in a format like '12345.99 ...'
Taxes for 7890.89: 697.99
Please input income values in a format like '12345.99 ...'
Taxes for 121212121212.12: 13333333163.33
Please input income values in a format like '12345.99 ...'
$

从命令行和每个管道:

$ ./income-tax.exe 1500.00 4500.25 1234567890123.00
Taxes for 1500.00: 55.00
Taxes for 4500.25: 325.02
Taxes for 1234567890123.00: 135802467743.53
$ echo "1500.00 4500.25 1234567890123.00" | ./income-tax.exe
Taxes for 1500.00: 55.00
Taxes for 4500.25: 325.02
Taxes for 1234567890123.00: 135802467743.53
//*************************************************
// A tax computing program for a multi-step tax bracket.
// The brackets are specified in the taxSteps array.
// The program is currency agnostic but assumes a 
// "unit" and "hundredths" (Dollar/Cent, Euro/Cent, Pound/Penny).
// It stores money values in those "hundredths" (e.g. Cents) 
// using 64 bit integers. (32 bit would not quite be enough
// for the highest earners; Elon Musk payed $11bn in 2021.)
// The tax rate is likewise stored in 1/100s of a percent
// to facilitate non-integer tax rates.
// All arithmetics are integer; resulting taxes are rounded down.
//
// The program accepts input as commandline arguments 
// ("income-tax 1234.56 777.88") or from standard input
// ("echo 1234.56 777.88 | income-tax").
// Iff standard input is a terminal it issues a prompt.

#include <stdio.h>
#include <stdint.h> // for 64 bit type
#include <assert.h>
#include <limits.h> // uint64_max
#include <inttypes.h>
#include <stdlib.h> // exit
#ifdef _MSC_VER // microsoft compiler, as opposed to *nix environment
#   define _CRT_SECURE_NO_WARNINGS // silence MSVC
#   pragma warning(disable : 4996) // MSVC prefers _isatty
#   include<io.h>
#else
#   include <unistd.h>
#endif

// Convenience function because of the unwieldy format strings.
// Prints "a string like "123.45" from 12345.
void printHundredths(uint64_t Hundredths)
{
    printf("%" PRIu64 ".%02" PRIu64, Hundredths / 100, Hundredths % 100);
}

/// A single tax step: An interval in centi-money units with a rate in "centipercent".
struct TaxStep
{
    uint64_t StepSizeInHundredths;
    unsigned int TaxRateInHundredthPercent;
};

uint64_t computeTaxesInHundredthsForStep(uint64_t incomeInHundredths, struct TaxStep taxStep)
{ 
    uint64_t taxedInThisStep 
        = incomeInHundredths < taxStep.StepSizeInHundredths 
        ? incomeInHundredths 
        : taxStep.StepSizeInHundredths;
    
    // Such a high income would overflow in the expression below and compute 
    // a tax amount that's much too low. The threshold, for 100% tax, is 
    // > 1.8E15 Hundredths, or 1.8E13 whatever (dollars, rupees). In rupees
    // we get close to a realistic income (one rupee ~ 1 cent), 1.8E12, 
    // 1.8 trillion dollars. If, say, Elon Musk liquidates its entire
    // stock at the zenith of his wealth, in Rupees or Lira, we could come close. 
    // Let's say that's OK for now.
    if (    taxStep.TaxRateInHundredthPercent != 0
        &&  taxedInThisStep > UINT64_MAX / taxStep.TaxRateInHundredthPercent)
    {
        fprintf(stderr, "Income ");
        printHundredths(incomeInHundredths);
        fprintf(stderr, " exceeds value range.\nMax permissible : ");
        printHundredths(UINT64_MAX / taxStep.TaxRateInHundredthPercent);
        exit(2);
    }

    // taxableMoney * HundredthsPercent is precise 
    // (and won't overflow, we asserted that above).
    // The division is exact to the cent, rounded down (we are a nice tax office).
    // The rate is in "centipercent", so we must then divide by 100*100.
    // With percent: "money*11/100" with "centipercent": "money*1100/10000".
    return (taxedInThisStep * taxStep.TaxRateInHundredthPercent) / 10000;
}

/// <summary>
/// Step through the tax bracket and apply the tax rate to each
/// step. The steps are interval sizes, not absolute values.
/// </summary>
/// <param name="incomeInHundredth">The income in cents or whatever</param>
/// <param name="taxSteps">The first element in an array of tax steps which have
/// an interval size and a rate for that interval.</param>
/// <returns></returns>

uint64_t computeTaxes(uint64_t incomeInHundredth, struct TaxStep* taxSteps)
{
    // The function simply calls itself with the remaining money
    // and the remaining tax brackets. Because the last interval is
    // UINT_MAX, incomeInHundredth <= taxSteps->StepSizeInHundredths
    // always triggers for the last interval, stopping the recursion.
    return computeTaxesInHundredthsForStep(incomeInHundredth, *taxSteps)
        + (   incomeInHundredth <= taxSteps->StepSizeInHundredths 
            ? 0 
            : computeTaxes(incomeInHundredth - taxSteps->StepSizeInHundredths, taxSteps+1)
          );
}

// A convenience function.
void errExit(const char* msg)
{
    fprintf(stderr, msg);
    exit(1); // indicates error
}

/// <summary>
/// Communicates the result of a parsing attempt. EOI is "end of information".
/// </summary>
enum ParseDiagE { ParseDiag_ERR, ParseDiag_EOI, ParseDiag_OK };

/// <summary>
/// A 64 return value which also carries an indicator whether
/// the value could be set properly from the input.
/// </summary>
struct ParseResult
{
    uint64_t parsedValue;
    enum ParseDiagE parseDiag;
};

/// <summary>
/// Factored out the common logic of the two parse methods below.
/// Sets the ret.parseDiag member appropriately, depending on the scanf diagnostic
/// return value (which indicates the number of parsed items and should be 2).
/// If the diag value is OK, combines the two numbers before and after the dot
/// to set ret.parsedValue,
/// </summary>
/// <returns>the result structure</returns>
struct ParseResult MakeParseResult(uint64_t incomeInInUnits, uint64_t IncomeFractionInHundredths, int scanfDiag)
{
    struct ParseResult ret = { 0, ParseDiag_OK };
    switch (scanfDiag)
    {
    case EOF:
        // typically OK: End of string, or end of file/pipe closed.
        ret.parseDiag = ParseDiag_EOI;
        break;
    case 0:
    case 1:
        // bad input: scanf should have read 2.
        ret.parseDiag = ParseDiag_ERR;
        break;
    }
    if (IncomeFractionInHundredths > 99)
    {
        // Could be parsed, but too many "cents", e.g. 1.234
        ret.parseDiag = ParseDiag_ERR;
    }

    if (ret.parseDiag == ParseDiag_OK)
    {
        // only if everything is OK, actually compute anything.
        ret.parsedValue = incomeInInUnits * 100 + IncomeFractionInHundredths;
    }
    return ret;
}

/// <summary>
/// Expects a number in the English float format [0-9]+\.[0-9]+
/// </summary>
/// <returns></returns>
struct ParseResult ParseIncomeInHundredthsFromString(const char* input)
{
    uint64_t incomeInInUnits = 0, IncomeFractionInHundredths = 0;

    int diag = sscanf(input, "%" SCNu64 ".%" SCNu64, &incomeInInUnits, &IncomeFractionInHundredths);
    return MakeParseResult(incomeInInUnits, IncomeFractionInHundredths, diag);
}

/// <summary>
/// Expects a number in the English float format [0-9]+\.[0-9]+
/// Output a prompt only if asked (do not spam sdout for batch runs).
/// </summary>
/// <returns></returns>
struct ParseResult ParseIncomeInHundredthsFromStream(FILE *stream, int prompt)
{
    if (prompt)
    {
        printf("Please input income values in a format like '12345.99 ...'\n");
    }
    uint64_t incomeInInUnits = 0, IncomeFractionInHundredths = 0;

    int diag = fscanf(stream, "%" SCNu64 ".%" SCNu64, &incomeInInUnits, &IncomeFractionInHundredths);
    return MakeParseResult(incomeInInUnits, IncomeFractionInHundredths, diag);
}

void PrintTaxBrackets(struct TaxStep *steps)
{
    uint64_t overallIncomeInHundredths = 0;
    printf("Tax brackets:\n");
    while(1)
    {
        if (steps->StepSizeInHundredths == UINT64_MAX)
        { 
            printf("Above: ");
            printHundredths(steps->TaxRateInHundredthPercent);
            printf("%%\n");
            break;
        }
        else
        {
            printHundredths(overallIncomeInHundredths);
            printf(" .. ");
            printHundredths(overallIncomeInHundredths += steps->StepSizeInHundredths);
            printf(": ");
            printHundredths(steps->TaxRateInHundredthPercent);
            printf("%%\n");
            ++steps;
        }
    }
}

int main(int argc, char** argv)
{
    // The specification of the tax brackets: A succession of intervals
    // with their respective tax rate, in "centipercent" (1120 would be 11.20%).
    // The last step **must** be of size UINT64_MAX (i.e., the remaining income),
    // that's how the program recognizes it's the last step
    struct TaxStep taxSteps[] = { {1000 * 100, 2 * 100}, {2000 * 100, 7 * 100}, {UINT64_MAX, 11 * 100 } };

    // If we have command line arguments we should process those.
    int ShouldProcessArgv = argc > 1;

    // If stdin is a terminal
    int inpIsFromTerminal = isatty(fileno(stdin));

    // spam stdout only for interactive sessions.
    if (!ShouldProcessArgv && inpIsFromTerminal)
    {
        PrintTaxBrackets(taxSteps);
    }

    /// Command line argument index. argv[0] is the program name,
    /// so we start with index 1 for the first actual argument.
    int argi = 1; 
    
    // loop through text command line arguments or textual numbers
    // from stdin.
    do
    {
        // Iff there are no command line arguments, we check standard input.
        // Apart from the input source, the processing is the same.
        struct ParseResult res = ShouldProcessArgv
            ? ParseIncomeInHundredthsFromString(argv[argi])
            : ParseIncomeInHundredthsFromStream(stdin, inpIsFromTerminal);

        if (res.parseDiag == ParseDiag_ERR)
        {
            errExit("Input format error\n");
        }
        else if (res.parseDiag == ParseDiag_EOI)
        {
            break;
        }
        printf("Taxes for ");
        printHundredths(res.parsedValue);
        printf(": ");
        printHundredths(computeTaxes(res.parsedValue, taxSteps));
        printf("\n");
    } while (ShouldProcessArgv ? ++argi < argc : 1);
    return 0;
}