减少if语句的数量

时间:2009-04-05 19:18:10

标签: c# conditional

到目前为止,我有以下程序:

using System;
namespace ParkingTicket
{
    class Program
    {
        static void Main()
        {
            int speed;
            int yrInSchool;
            double fine;
            char choice = ' ';
            do
            {
                Console.Clear();
                speed = GetSpeed();
                if (speed <= 15)
                    Console.WriteLine("No speeding fine to pay.");
                else
                {
                    yrInSchool = GetYrInSchool();
                    fine = CalculateFine(speed, yrInSchool);
                    DisplayFine(fine);
                }
                choice = GetUserChoice();
            } while (choice != 'Q' && choice != 'q');
        }
        static int GetSpeed()
        {
            int speed;
            string userInput;
            try
            {
                Console.Write("Please enter the speed you were traveling: ");
                userInput = Console.ReadLine();
                speed = Convert.ToInt32(userInput);
            }
            catch
            {
                Console.WriteLine("\a\n INVALID - PLEASE TRY AGAIN");
                Console.Write("Please press enter to continue....");
                userInput = Console.ReadLine();
                speed = GetSpeed();  // this is the recursion - calling myself

            }
            return speed;

            // code this method
        }
        static int GetYrInSchool()
        {
            string userEntry;
            int year;

            /*************************************************************
             *  modify this method to validate the year using a Try/Catch
             *************************************************************/
            Console.WriteLine("\nClassifications");
            Console.WriteLine("\tFreshman  (enter 1)");
            Console.WriteLine("\tSophomore (enter 2)");
            Console.WriteLine("\tJunior    (enter 3)");
            Console.WriteLine("\tSenior    (enter 4)");

            try
            {
                Console.Write("Enter choice: ");
                userEntry = Console.ReadLine();
                year = Convert.ToInt32(userEntry);
            }

            catch
            {
                Console.WriteLine("\a\n INVALID - PLEASE TRY AGAIN");
                Console.Write("Please press enter to continue....");
                userEntry = Console.ReadLine();
                year = GetYrInSchool();  // this is the recursion - calling myself
            }
            return year;
        }
        static double CalculateFine(int speed, int year)
        {
            const double COST_PER_5_OVER = 87.50;
            const int SPEED_LIMIT = 15;
            const double INITIAL_FEE = 75.00;
            double fine = 0;

            if (((year == 1) && (speed >= 15) || (speed <= 19)))
            {
                fine = INITIAL_FEE - 50.00;
            }
            else if (((year == 1) && (speed >= 20) || (speed >= 24)))
            {
                fine += (INITIAL_FEE - 50.00) + COST_PER_5_OVER;
            }
            else if (((year == 1) && (speed >= 25) || (speed <= 29)))
            {
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 2);
            }
            else if (((year == 1) && (speed >= 30) || (speed <= 34)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 3);
            else if (((year == 1) && (speed >= 35) || (speed <= 39)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 4);
            else if (((year == 1) && (speed >= 40) || (speed <= 44)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 5);
            else if (((year == 1) && (speed >= 45) || (speed <= 49)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 6);
            if (((year == 1) && (speed >= 50) || (speed <= 54)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 7);
            if (((year == 1) && (speed >= 55) || (speed <= 59)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 8);
            if (((year == 1) && (speed >= 60) || (speed <= 64)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 9);
            if (((year == 1) && (speed >= 65) || (speed <= 69)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 10);
            if (((year == 1) && (speed >= 70) || (speed <= 74)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 11);
            if (((year == 1) && (speed >= 75) || (speed <= 79)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 12);
            if (((year == 1) && (speed >= 80) || (speed <= 84)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 13);
            if (((year == 1) && (speed >= 85) || (speed <= 89)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 14);
            if (((year == 1) && (speed >= 90) || (speed <= 94)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 15);
            if (((year == 1) && (speed >= 95) || (speed <= 99)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 16);
            if (((year == 1) && (speed >= 100) || (speed <= 104)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 17);
            if (((year == 1) && (speed >= 105) || (speed <= 109)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 18);
            if (((year == 1) && (speed >= 110) || (speed <= 114)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 19);
            if (((year == 1) && (speed >= 115) || (speed <= 119)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 20);
            if (((year == 1) && (speed >= 120) || (speed <= 124)))
                fine = (INITIAL_FEE - 50.00) + (COST_PER_5_OVER * 21);
            else if (((year == 2) && (speed >= 16) || (speed <= 19)))
                fine = INITIAL_FEE;
            if (((year == 2) && (speed >= 20) || (speed <= 24)))
                fine = INITIAL_FEE + (COST_PER_5_OVER);
            if (((year == 2) && (speed >= 25) || (speed <= 29)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 2);
            if (((year == 2) && (speed >= 30) || (speed <= 34)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 3);
            if (((year == 2) && (speed >= 35) || (speed <= 39)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 3);
            if (((year == 2) && (speed >= 40) || (speed <= 44)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 4);
            if (((year == 2) && (speed >= 45) || (speed <= 49)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 5);
            if (((year == 2) && (speed >= 50) || (speed <= 54)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 6);
            if (((year == 2) && (speed >= 55) || (speed <= 59)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 7);
            if (((year == 2) && (speed >= 60) || (speed <= 64)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 8);
            if (((year == 2) && (speed >= 65) || (speed <= 69)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 9);
            if (((year == 2) && (speed >= 70) || (speed <= 74)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 10);
            if (((year == 2) && (speed >= 75) || (speed <= 79)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 11);
            if (((year == 2) && (speed >= 80) || (speed <= 84)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 12);
            if (((year == 2) && (speed >= 85) || (speed <= 89)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 13);
            if (((year == 2) && (speed >= 90) || (speed <= 94)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 14);
            if (((year == 2) && (speed >= 95) || (speed <= 99)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 15);
            if (((year == 2) && (speed >= 100) || (speed <= 104)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 16);
            if (((year == 2) && (speed >= 105) || (speed <= 109)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 17);
            if (((year == 2) && (speed >= 110) || (speed <= 114)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 18);
            if (((year == 2) && (speed >= 115) || (speed <= 119)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 19);
            if (((year == 2) && (speed >= 120) || (speed <= 124)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 20);
            if (((year == 2) && (speed >= 125) || (speed <= 129)))
                fine = INITIAL_FEE + (COST_PER_5_OVER * 21);
            else if (((year == 3) && (speed >= 16) || (speed <= 19)))
                fine = INITIAL_FEE + 50.00;
            if (((year == 3) && (speed >= 20) || (speed <= 24)))
                fine = INITIAL_FEE + 50.00 + (COST_PER_5_OVER);
            if (((year == 3) && (speed >= 25) || (speed <= 29)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 2);
            if (((year == 3) && (speed >= 30) || (speed <= 34)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 3);
            if (((year == 3) && (speed >= 35) || (speed <= 39)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 4);
            if (((year == 3) && (speed >= 40) || (speed <= 44)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 5);
            if (((year == 3) && (speed >= 45) || (speed <= 49)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 6);
            if (((year == 3) && (speed >= 50) || (speed <= 54)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 7);
            if (((year == 3) && (speed >= 55) || (speed <= 59)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 8);
            if (((year == 3) && (speed >= 60) || (speed <= 64)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 9);
            if (((year == 3) && (speed >= 65) || (speed <= 69)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 10);
            if (((year == 3) && (speed >= 70) || (speed <= 74)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 11);
            if (((year == 3) && (speed >= 75) || (speed <= 79)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 12);
            if (((year == 3) && (speed >= 80) || (speed <= 84)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 13);
            if (((year == 3) && (speed >= 85) || (speed <= 89)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 14);
            if (((year == 3) && (speed >= 90) || (speed <= 94)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 15);
            if (((year == 3) && (speed >= 95) || (speed <= 99)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 16);
            if (((year == 3) && (speed >= 100) || (speed <= 104)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 17);
            if (((year == 3) && (speed >= 105) || (speed <= 109)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 18);
            if (((year == 3) && (speed >= 110) || (speed <= 114)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 19);
            if (((year == 3) && (speed >= 115) || (speed <= 119)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 20);
            if (((year == 3) && (speed >= 120) || (speed <= 124)))
                fine = (INITIAL_FEE + 50.00) + (COST_PER_5_OVER * 21);
            else if (((year == 4) && (speed >= 16) || (speed <= 19)))
                fine = INITIAL_FEE + 100.00;
            if (((year == 4) && (speed >= 20) || (speed <= 24)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER);
            if (((year == 4) && (speed >= 25) || (speed <= 29)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 2);
            if (((year == 4) && (speed >= 30) || (speed <= 34)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 3);
            if (((year == 4) && (speed >= 35) || (speed <= 39)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 4);
            if (((year == 4) && (speed >= 40) || (speed <= 44)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 5);
            if (((year == 4) && (speed >= 45) || (speed <= 49)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 6);
            if (((year == 4) && (speed >= 100) || (speed <= 54)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 7);
            if (((year == 4) && (speed >= 55) || (speed <= 59)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 8);
            if (((year == 4) && (speed >= 60) || (speed <= 64)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 9);
            if (((year == 4) && (speed >= 65) || (speed <= 69)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 10);
            if (((year == 4) && (speed >= 70) || (speed <= 74)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 11);
            if (((year == 4) && (speed >= 75) || (speed <= 79)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 12);
            if (((year == 4) && (speed >= 80) || (speed <= 84)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 13);
            if (((year == 4) && (speed >= 85) || (speed <= 89)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 14);
            if (((year == 4) && (speed >= 90) || (speed <= 94)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 15);
            if (((year == 4) && (speed >= 95) || (speed <= 99)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 16);
            if (((year == 4) && (speed >= 100) || (speed <= 104)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER);
            if (((year == 4) && (speed >= 105) || (speed <= 109)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 18);
            if (((year == 4) && (speed >= 110) || (speed <= 114)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 19);
            if (((year == 4) && (speed >= 115) || (speed <= 119)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 20);
            if (((year == 4) && (speed >= 120) || (speed <= 124)))
                fine = (INITIAL_FEE + 100.00) + (COST_PER_5_OVER * 21);

            // finish coding this method

            return fine;
        }

        static void DisplayFine(double fine)
        {
            Console.WriteLine("Fine: {0:C}", fine);
        }

        static char GetUserChoice()
        {
            Console.Write
                ("\nPress \"C\" to [C]ontinue or \"Q\" to [Q]uit: ");
            string userEntry = Console.ReadLine();
            char choice = Convert.ToChar(userEntry);
            Console.WriteLine("------------------------------------");
            return choice;
        }
    }
}

我有一份完整的列表,这些声明最高可达125英里/小时,不同年份:1到4.我正在尝试制作一个程序,根据车辆的速度输入,然后根据速度提供适当的车票信息

速度限制为15英里/小时。每超过5英里的速度限制,总计增加87.50美元。 2年级是大二学生,因此需要50.00美元的折扣。然而,就像第4年一样,总额增加了100美元的费用。我为每个速度得到相同的总数。为什么?

9 个答案:

答案 0 :(得分:13)

其他人对运营商优先权的看法似乎是正确的,但我认为这里有一个更大的问题。你真的不需要数以万计的if语句来模拟这个问题。我相信你现在已经发现这种方法不可维护。试图改变那堆ifs中的任何东西将是一个真正的痛苦并且非常容易出错。

我要做的第一件事是将折扣的计算与罚款的计算分开。这样您就不必手动计算折扣和罚款的每种可能组合。这就是我所说的:

static double CalculateFine(int speed, int year)
{
    const double COST_PER_5_OVER = 87.5;
    const int SPEED_LIMIT = 15;
    const double INITIAL_FEE = 75;

    // Should there be a fine at all?
    if (speed > SPEED_LIMIT) {
        // The discount is 50 for each year, scaled so that year 1 is
        // -50, year 2 is 0, and so on.
        double discount = year * 50 - 100;

        // Now calculate the standard fee.
        int feeMultiplier = (speed - SPEED_LIMIT) / 5;
        double fine = feeMultiplier * COST_PER_5_OVER + INITIAL_FEE;

        return discount + fine;
    }
    return 0.;
}

最后,折扣和罚款仅合并一次。真的,这只是弄清楚用什么公式来计算罚款,然后实施。如果以更随意的方式定义罚款,那么表格可能会有用。

答案 1 :(得分:1)

(speed >= 50) || (speed <= 54)

如果您希望这意味着“速度在50到54之间”,那么您的逻辑就会出错。你想要而不是或。

我不知道这里的礼仪是什么,提供一个实际的答案,而不是指导那里的人,但这是你应该瞄准的事情。我没有亲自测试过。

static double CalculateFine(int speed, int year)
{
    const double COST_PER_5_OVER = 87.50;
    const int SPEED_LIMIT = 15;
    const double INITIAL_FEE = 75.00;
    double fine = 0;

    if(speed <= SPEED_LIMIT)
    {
        return 0; // No fine imposed
    }

    fine = INITIAL_FEE;

    // Adjust for the different years
    switch(year) {
        case 1:
            fine -= 50;
            break;
        case 2:
            // nowt
            break;
        case 3:
            fine += 50;
            break;
        case 4:
            fine += 100;
    }

    // Add the remaining fine for each 5 miles over the limit
    // XXX: This is slightly different from yours, in that past 125,
    // it'll still keep adding COST_PER_5_OVER
    int perFiveOver = (int)Math.Floor((speed - SPEED_LIMIT) / 5);
    fine += (perFiveOver * COST_PER_5_OVER);

    return fine;

}

答案 2 :(得分:1)

这不是一个直接的答案(我认为其他人已经很好地介绍了这一点)你可能想查看Steve McConnell的书 Code Complete 。它包含避免上述代码的最佳实践。它可以帮助你完成未来的项目。

答案 3 :(得分:0)

嘿,我有点困惑,应该是

((year == 1) && (speed >= 50) && (speed <= 54))

答案 4 :(得分:0)

我认为你混淆了运算符的优先级和语义。

首先,你想说(speed&gt; = 50)&amp;&amp; (速度&lt; = 54)

其次,在C&amp;&amp;具有更高的优先级,因此您的表达式意味着: 如果(年== 1和速度&gt; = 50)或(如果我的速度低于54)......

第三,你有一对额外的()表明你打算以不同的方式对事物进行优先排序。

最后,我会提到有一堆类似的查找语句的代码编写得相当糟糕。实现它的更好方法是使用表或数据结构来表示范围,或者至少是更好的组织。

====

更新: 现在你已经发布了代码,看起来你真的在努力工作...... 首先,如果或基于年份切换(应该只有大约4年)。对于每年,调用一个单独的函数来进行计算,这将是更清洁的。 例如:

if(year==1) return calculateFineForYear1(speed);
if(year==2) return ...

(我不知道C#,但应该有某种switch语句)

现在您可以分别管理每年。 由于您的条件是以速度递增的顺序,您可以执行以下操作:

if(speed<50) return 0;
if(speed<55) return ...;
if(speed<60) return ...;
if(speed<65) return ...

它仍然远非完美,但它已经更加清洁和易于管理。

现在,看着你的ifs,看起来你甚至不需要那么多ifs, 因为你付的是50 + C *差异, 那么为什么不只计算差异(速度-50)然后只返回计算结果呢?

例如:

Int total_above_limit = (speed – SPEED_LIMIT);
Int increments_of_5_above_limit = (total_above_limit)/5
Return ( (INITIAL_FEE – 50) + COST_PER_5_OVER*increments_of_5_above_limit))

(我不知道C#,我只是猜测语法)

答案 5 :(得分:0)

不确定我是否100%确定您的代码尝试做什么,但问题是逻辑运算符的优先级,即应该是:

if(((year == 1)&amp;&amp;((speed&gt; = 50)||(speed&lt; = 54))))fine =(INITIAL_FEE - 50.00)+(COST_PER_5_OVER * 7);

注意速度不等式周围的额外括号。

答案 6 :(得分:0)

那些if语句让我的眼睛流血 - 而且它们也不一致。你在第一个范围的速度上有一个错误 - 第1年,速度为15会让你被罚款。在某些情况下,您使用大量if语句,而在其他语句中使用/ elseif语句。有一点不同 - 尤其是当您测试速度是否<=某个数字时。 (带有||或子句的一堆if语句将各自评估为true,if / else语句将仅评估第一个语句)。你可能意味着&amp;&amp; (和)而不是|| (或) - 但你应该为每个人的理智取代那些if语句。 ;)

找出公式,并将代码 - 而不是结果。它看起来像是[1]:

    const double COST_PER_5_OVER = 87.50;
    const int SPEED_LIMIT = 15;
    const double INITIAL_FEE = 75.00;

    if (speed <= SPEED_LIMIT)
    {
         return 0;
    }

    double yearSurcharge;
    switch (year)
    {
        case 1:
           yearSurcharge = -50;
           break;
        case 2:
           yearSurcharge = 0;
           break;
        case 3:
            yearSurcharge = 50;
            break;
        case 4:
            yearSurcharge = 100;
            break;
        default:
            yearSurcharge = 0;
            break;
    }

    const int NUMBER_OF_FIVE_OVER = 21;
    int numberOfFiveOver = Math.Min((speed - SPEED_LIMIT) % 5; MAX_NUMBER_OF_FIVE_OVER)

    return INITIAL_FEE + yearSurcharge + (numberOfFiveOver * COST_PER_5_OVER);

可以简化为以下内容:

    if (speed > SPEED_LIMIT) {
         return INITIAL_FEE 
                + (year == 1 ? -50 : year == 3 ? 50 : year == 4 ? 100 : 0) 
                + Math.Min((speed - SPEED_LIMIT) % 5, MAX_NUMBER_OF_FIVE_OVER) * COST_PER_5_OVER;
    } else {
         return 0;
    }

虽然有些人会对年份部分的嵌套三元组进行狡辩。

[1]从技术上讲,你对超过125的任何东西都有0美元的罚款 - 但我认为这不是你想要的。

答案 7 :(得分:0)

表格驱动的方法应该在这里运作良好。在表中定义值,然后迭代它们以找到匹配的值,然后使用它来进行计算。这很好用,您可以轻松添加/编辑/删除条目而无需触及代码 - 完全可以。

您可以从简单的静态分配和定义的表开始。如果需要,您可以从其他源(例如XML文件)动态加载表。

答案 8 :(得分:0)

如果If语句至少包含一个或多个'嵌套'If语句,通常会使用switch语句...