Calculation problem

Ok, the problem I am having is with the tax calculations. It is not calculating right for autos which is type A, but it is calculating correctly for cycles which is type M. All the numbers are correct, percentages are right, equations are all right. I am at a loss on what could be wrong with just the autos. The number that's the issue is the second one from the right on the output to screen.

What am I not seeing??

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#include<iostream>
#include<fstream>
#include<string>
#include<iomanip>
#include<sstream>

using namespace std;

//CONSTANTS
const string FILENAME_IN = "REGISTER.txt",
        FILENAME_H = "HOUSEHOLDS.txt",
        FILENAME_V = "VEHICLES.txt";
const int CURRENT_YEAR = 2013,
        FULL = 20; 
const float AUTO_ROAD_FEE = 24.00,
        CYCLE_ROAD_FEE = 12.00,
        LICENSE_PERCENT= .0025,
        AGE_RANGE1 = 5,
        RANGE1_PERCENT_MSRP_AUTO = .03,
        RANGE1_PERCENT_AGE_AUTO = .0015,
        RANGE1_PERCENT_MSRP_CYCLE = .025,
        RANGE1_PERCENT_AGE_CYCLE = .0009,
        AGE_RANGE2_MIN = 6,
        AGE_RANGE2_MAX = 10,
        RANGE2_PERCENT_MSRP_AUTO = .0275,
        RANGE2_PERCENT_AGE_AUTO = .0012,
        RANGE2_PERCENT_MSRP_CYCLE = .0225,
        RANGE2_PERCENT_AGE_CYCLE = .0009,
        AGE_RANGE3_MIN = 11,
        AGE_RANGE3_MAX = 15,
        RANGE3_PERCENT_MSRP_AUTO = .025,
        RANGE3_PERCENT_AGE_AUTO = .0009,
        RANGE3_PERCENT_MSRP_CYCLE = .02,
        RANGE3_PERCENT_AGE_CYCLE = .0009,
        AGE_RANGE4 = 15,
        AGE_RANGE4_TAX_AUTO = 20.00,
        AGE_RANGE4_TAX_CYCLE = 10.00;

//FUNCTION PROTOTYPES
void getRoadFee(char& type, float& roadFee);
void getTax(char& type, float& msrp, int& age, float& tax);
void readRegister (ifstream& inRegister, int& houseid, int& year,
        float& msrp, string& plate, char& type, int& age, float& tax,
        float& roadFee);

int main()
{
     int houseid = 0,
             year = 0,
             full = 0,
             age = 0,
             lineNum = 0,
             noOfVehicles = 0;
     float msrp = 0,
             roadFee = 0,
             licenseFee = 0,
             tax = 0,
             total = 0;
     char type,
             ch;
     string plate;
     cout << "This program will read data from REGISTER.txt"
           "\nand output data into HOUSEHOLDS.txt and VEHICLES.txt"
             << endl << endl;

     ifstream inRegister;          //ifstream
     inRegister.open (FILENAME_IN.c_str());          //open file

     if(!inRegister)          //if not open
          cout << "Error opening input file " << FILENAME_IN << endl;

     inRegister >> houseid;             //prime read

     while (inRegister)
     {
          readRegister (inRegister, houseid, year, msrp, plate, type, age, tax,
                  roadFee);
          inRegister >> houseid;
          
     }

     cout << "\nHousehold ID Number \t" << "Vehicles Registered \t"
             << "Total Charges\n";
     cout << fixed << showpoint << setprecision(2) << houseid << "\t"
             << setw(21) << noOfVehicles << setw(19) << "\t" << "$"
             << right << total;

     ofstream outHouse,
             outVehicles;
     outHouse.open (FILENAME_H.c_str());
     outVehicles.open (FILENAME_V.c_str());

system("pause");
     return 0;
}

/******************************************************************
 * readRegister: reads REGISTER.txt file
 * input: ifstream inRegister, int houseid, int year, float msrp, string plate,
 * char type, int age, float tax, float roadFee
 * processes: gets file info, calculates tax, and calculates road fee
 * output: tax and road fee
******************************************************************/
void readRegister (ifstream& inRegister, int& houseid, int& year,
        float& msrp, string& plate, char& type, int& age, float& tax,
        float& roadFee)
{
     char ch;
     float licenseFee = 0,
             total = 0;

     inRegister.get(ch);                   //read space

     while (inRegister && ch != '\n')
     {
          inRegister >> type >> plate >> year >> msrp;// read rest of info
          age = CURRENT_YEAR - year;
          licenseFee = msrp * LICENSE_PERCENT;
          getRoadFee(type, roadFee);              //get road fee function
          getTax(type, msrp, age, tax);           //get tax function
          total = roadFee + licenseFee + tax;
          inRegister.get(ch);                //read space
          cout << houseid << ' ' << type << ' ' << plate << ' ' << year
                  << ' ' << msrp << ' ' << ' ' << roadFee << ' '
                  << licenseFee << ' ' << tax << ' ' <<  total << endl;
     }

     return;
}

/******************************************************************
 * getRoadFee: calculates road fee for each vehicle
 * input: char type, float roadFee
 * output: road fee for specific type of vehicle
******************************************************************/
void getRoadFee(char& type, float& roadFee)
{
     switch (type)
          {
               case 'A':
                    roadFee = AUTO_ROAD_FEE;
                    break;
               case 'M':
                    roadFee = CYCLE_ROAD_FEE;
                    break;
          }
}

/******************************************************************
 * getTax: calculates tax for each vehicle
 * input: char type, float msrp, int age, float tax
 * output: tax for each vehicle
******************************************************************/
void getTax(char& type, float& msrp, int& age, float& tax)
{
     if(type == 'A' && age <= AGE_RANGE1)
          tax = (RANGE1_PERCENT_MSRP_AUTO * msrp) -
                  (RANGE1_PERCENT_AGE_AUTO * age * msrp);
     if(type == 'A' && age >= AGE_RANGE2_MIN ||
             age <= AGE_RANGE2_MAX)
          tax = (RANGE2_PERCENT_MSRP_AUTO * msrp) -
                  (RANGE2_PERCENT_AGE_AUTO * age * msrp);
     if(type == 'A' && age >= AGE_RANGE3_MIN ||
             age <= AGE_RANGE3_MAX)
          tax = (RANGE3_PERCENT_MSRP_AUTO * msrp) -
                  (RANGE3_PERCENT_AGE_AUTO * age * msrp);
     if(type == 'A' && age > AGE_RANGE4)
         tax = AGE_RANGE4_TAX_CYCLE;

     
     if(type == 'M' && age <= AGE_RANGE1)
          tax = (RANGE1_PERCENT_MSRP_CYCLE * msrp) -
                  (RANGE1_PERCENT_AGE_CYCLE * age * msrp);
     if(type == 'M' && age >= AGE_RANGE2_MIN ||
             age <= AGE_RANGE2_MAX)
          tax = (RANGE2_PERCENT_MSRP_CYCLE * msrp) -
                  (RANGE2_PERCENT_AGE_CYCLE * age * msrp);
     if(type == 'M' && age >= AGE_RANGE3_MIN ||
             age <= AGE_RANGE3_MAX)
          tax = (RANGE3_PERCENT_MSRP_CYCLE * msrp) -
                  (RANGE3_PERCENT_AGE_CYCLE * age * msrp);
     if(type == 'M' && age > AGE_RANGE4)
         tax = AGE_RANGE4_TAX_CYCLE;
}
closed account (o3hC5Di1)
Hi there,

Could you provide an example of the input you give + the output you get, and then an example of the ouput you're expecting?

It would help us determine the problem faster, seeing as we're not aware of the details of the program and calculations required.

Thanks,
All the best,
NwN
Duh, Sorry forgot that you would need a data file. The problem is with the tax amount which then throws off the the total, just for autos though which makes no sense to me because the M - cycle calculations are right.

Here is one of the lines for REGISTER.txt:

333333 A FFF888 2000 12345 M BBB888 2000 9988 M GHW888 1990 7711

This should output the:
cout << houseid << ' ' << type << ' ' << plate << ' ' << year
<< ' ' << msrp << ' ' << ' ' << roadFee << ' '
<< licenseFee << ' ' << tax << ' ' << total << endl;

Which should be:
333333 A FFF888 2000 12345 24 30.8625 164.1885 219.05
333333 M BBB888 2000 9988 12 24.97 82.9004 119.87
333333 M GHW888 1990 7711 12 19.2775 10 41.2775

But what I am getting is:
333333 A FFF888 2000 12345 24 30.8625 102.464 157.326
333333 M BBB888 2000 9988 12 24.97 82.9004 119.87
333333 M GHW888 1990 7711 12 19.2775 10 41.2775

Also, how do I combine the totals from the multiple vehicles from one household into a grand total for the house? So using the data above I would need the code to add the last number on each of the 333333 lines together to give me the total due for the entire household.
closed account (o3hC5Di1)
Hi there,

I'm not exactly sure about this, but it would be worth a try:

154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
void getTax(char& type, float& msrp, int& age, float& tax)
{
     if(type == 'A' && age <= AGE_RANGE1)
          tax = (RANGE1_PERCENT_MSRP_AUTO * msrp) -
                  (RANGE1_PERCENT_AGE_AUTO * age * msrp);
     if(type == 'A' && age >= AGE_RANGE2_MIN ||
             age <= AGE_RANGE2_MAX)
          tax = (RANGE2_PERCENT_MSRP_AUTO * msrp) -
                  (RANGE2_PERCENT_AGE_AUTO * age * msrp);
     if(type == 'A' && age >= AGE_RANGE3_MIN ||
             age <= AGE_RANGE3_MAX)
          tax = (RANGE3_PERCENT_MSRP_AUTO * msrp) -
                  (RANGE3_PERCENT_AGE_AUTO * age * msrp);
     if(type == 'A' && age > AGE_RANGE4)
         tax = AGE_RANGE4_TAX_CYCLE;

     
     if(type == 'M' && age <= AGE_RANGE1)
          tax = (RANGE1_PERCENT_MSRP_CYCLE * msrp) -
                  (RANGE1_PERCENT_AGE_CYCLE * age * msrp);
     if(type == 'M' && age >= AGE_RANGE2_MIN ||
             age <= AGE_RANGE2_MAX)
          tax = (RANGE2_PERCENT_MSRP_CYCLE * msrp) -
                  (RANGE2_PERCENT_AGE_CYCLE * age * msrp);
     if(type == 'M' && age >= AGE_RANGE3_MIN ||
             age <= AGE_RANGE3_MAX)
          tax = (RANGE3_PERCENT_MSRP_CYCLE * msrp) -
                  (RANGE3_PERCENT_AGE_CYCLE * age * msrp);
     if(type == 'M' && age > AGE_RANGE4)
         tax = AGE_RANGE4_TAX_CYCLE;
}


Let's consider one block:

1
2
3
4
5
6
7
8
9
10
11
12
13
 if(type == 'A' && age <= AGE_RANGE1)  //this happens when age < AGE_RANGE1,  fine
          tax = (RANGE1_PERCENT_MSRP_AUTO * msrp) -
                  (RANGE1_PERCENT_AGE_AUTO * age * msrp);
     if(type == 'A' && age >= AGE_RANGE2_MIN ||   //this happens when age < AGE_RANGE2
             age <= AGE_RANGE2_MAX)               //OR when age < AGE_RANGE_2_MAX
          tax = (RANGE2_PERCENT_MSRP_AUTO * msrp) -
                  (RANGE2_PERCENT_AGE_AUTO * age * msrp);
     if(type == 'A' && age >= AGE_RANGE3_MIN ||
             age <= AGE_RANGE3_MAX)
          tax = (RANGE3_PERCENT_MSRP_AUTO * msrp) -
                  (RANGE3_PERCENT_AGE_AUTO * age * msrp);
     if(type == 'A' && age > AGE_RANGE4)
         tax = AGE_RANGE4_TAX_CYCLE;


The OR || you are using is always going to be true, because when an age is smaller than age range1, it's always going to be smaller than age_range2_max. Solution:twofold, change thos OR's to && (AND), and I would suggest to change the structure to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if(type == 'A' )
{
     if (age <= AGE_RANGE1) 
          tax = (RANGE1_PERCENT_MSRP_AUTO * msrp) -
                  (RANGE1_PERCENT_AGE_AUTO * age * msrp);
     else if (age >= AGE_RANGE2_MIN &&  age <= AGE_RANGE2_MAX)   //between MIN and MAX
          tax = (RANGE2_PERCENT_MSRP_AUTO * msrp) -
                  (RANGE2_PERCENT_AGE_AUTO * age * msrp);
     else if (age >= AGE_RANGE3_MIN && age <= AGE_RANGE3_MAX)
          tax = (RANGE3_PERCENT_MSRP_AUTO * msrp) -
                  (RANGE3_PERCENT_AGE_AUTO * age * msrp);
     else if (age > AGE_RANGE4)
         tax = AGE_RANGE4_TAX_CYCLE;
}

//same for type=='M' 


Regarding the totals, you would need to do it here, because that's where the line is parsed:

104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
void readRegister (ifstream& inRegister, int& houseid, int& year,
        float& msrp, string& plate, char& type, int& age, float& tax,
        float& roadFee)
{
     char ch;
     float licenseFee = 0,
             total = 0.
             house_total=0; //create a total variable

     inRegister.get(ch);                   //read space

     while (inRegister && ch != '\n')
     {
          inRegister >> type >> plate >> year >> msrp;// read rest of info
          age = CURRENT_YEAR - year;
          licenseFee = msrp * LICENSE_PERCENT;
          getRoadFee(type, roadFee);              //get road fee function
          getTax(type, msrp, age, tax);           //get tax function
          total = roadFee + licenseFee + tax;
          housetotal += total; //increment the house_total with current items's total 
          inRegister.get(ch);                //read space
          cout << houseid << ' ' << type << ' ' << plate << ' ' << year
                  << ' ' << msrp << ' ' << ' ' << roadFee << ' '
                  << licenseFee << ' ' << tax << ' ' <<  total << endl;
     }
     
     std::cout << "----- Household total: " << house_total; //output it

     return;
}


One or two things you may want to look into are:
- io manipulators for formatting the output (setw in particular)
- have some functions return by value, for instance it would seem more natural if getTax() returned the actual tax rather than changing an input parameter:

1
2
3
4
5
6
7
8
9
10
float getTax(char& type, float& msrp, int& age)
{
    float tax;   
    //calculate tax
   return tax;
}

//usage in another function:
float tax;
tax = getTax('M', 1234, 4);



Hope that helps.

All the best,
NwN
Topic archived. No new replies allowed.