IElite
IElite

Reputation: 1848

How can I know why my program calculations and output is incorrect?

I'm working on a programming problem.

Note: This is not a student project. I am working on this for a new Quest for the website Try My Quest Dot Com, for which i am the admin.

Problem:

Jenny just started work as a programmer for Justine's Java Workshop. She is paid $10 an hour, with a few exceptions. She earns an extra $1.50 an hour for any part of a day where she works more than 8 hours, and an extra $2.50 an hour for hours beyond 40 in any one week. Also, she earns a 125% bonus for working on Saturday, and a 50% bonus for working on Sunday. The bonuses for Saturday and Sunday are computed based on the hours worked those days; they are not used to calculate any bonus for working more than 40 hours in a week. You'll be given the number of hours Jenny worked each day in a week (Sunday, Monday, etc ), and you need to compute her salary for the week. The input will be positive integers, less than or equal to 24. The output must be formatted with a dollar sign and rounded up to the nearest penny. For example, $2" and $2.136666" are wrong answers; the correct versions are $2.00" and $2.14", respectively.

Anyway, i am trying to write this in Delphi (No form project). I pass the program a command line argument - timecard.dat

input

0, 8, 8, 8, 8, 8, 0
0, 10, 10, 10, 10, 10, 0
0, 0, 8, 8, 8, 8, 8
0, 0, 0, 10, 10, 10, 10
10, 10, 10, 9, 9, 9, 9

Output

Output #1: $400.00
Output #2: $540.00
Output #3: $500.00
Output #4: $540.75
Output #5: $905.88

My Out put however is:

Output #1: $400.00
Output #2: $540.00
Output #3: $500.00

Output #4: $537.00
Output #5: $902.50

The last two output values of mine are different from the actual results. Not sure why, and the more i stare at the code, the less i see it

Can anyone tell me what i have done wrong?

program ACSL_Time_Cards;
{assumes Sunday = 1, Monday 3, etc}
uses
  SysUtils,
  Dialogs;

const
 HourlyWage = 10.00;
 OverEightWage = 1.50;
 OverFortyWage = 2.50;
var
 F: TextFile;
 I, ArrayIndex: Integer;
 WeeklyHours: Array[0..6] of Integer; //weekly hours
 HourStr, LineStr: String;
 TotalHours, TotalOverFortyHours, TotalOverEightHours, TotalSatHours, TotalSunHours: Integer;
 TotalWages: Real;
begin
 //initialize variables
 TotalHours:= 0;
 TotalOverEightHours:= 0;
 TotalOverFortyHours:= 0;
 TotalSatHours:= 0;
 TotalSunHours:= 0;
 TotalWages:= 0.00;
 ArrayIndex:= 0;
 //open file "timecard.dat" for input
 if FileExists(ParamStr(1)) then
 begin
  AssignFile(F, ParamStr(1));
  Reset(F);
  //step through file and extract each line and store in hoursStr
  while not EOF(F) do
  begin
   Readln(F, LineStr);
   //step through hours string and fill Array with weekly hours
   for I:= 1 to length(LineStr) do
   begin
    //if character is not a ',' then add it to hourStr
    if LineStr[I] <> ',' then
     HourStr:= HourStr + LineStr[I]
    else
    begin
     //add HourStr to Array
     WeeklyHours[ArrayIndex]:= StrToInt(HourStr);
     //reset the variable
     HourStr:= '';
     //increment Variable
     Inc(ArrayIndex);
    end; //else
   end; //for I:= 1 to length(HoursStr) do
   //clean up by adding the last remaining one
   WeeklyHours[ArrayIndex]:= StrToInt(HourStr);
   //step through array and figure out overtime Daily and Weekly
   for I:= Low(WeeklyHours) to High(WeeklyHours) do
   begin
    TotalHours:= TotalHours + WeeklyHours[I];
    if WeeklyHours[I] > 8 then
     TotalOverEightHours:= TotalOverEightHours + WeeklyHours[I]-8;
     //get sunday hours
     if I + 1 = 1 then
      TotalSunHours:= TotalSunHours + WeeklyHours[I];
     //get saturday hours
     if I + 1 = 7 then
     TotalSatHours:= TotalSatHours + WeeklyHours[I];
   end;
   //get total over 40 hours
   if TotalHours > 40 then
    TotalOverFortyHours:= TotalHours-40;
  //compute Regular Hours
  TotalWages:= TotalWages + TotalHours * 10.00;
  //compute overtime hours

  TotalWages:= TotalWages + TotalOverEightHours * 1.50;
  TotalWages:= TotalWages + TotalOverFortyHours * 2.50;
  //compute bonuses
  TotalWages:= TotalWages + (TotalSatHours * 10.00) * 1.25;
  TotalWages:= TotalWages + (TotalSunHours * 10.00) * 0.50;

  ShowMessage('TotalWages: ' + FormatFloat('$0.00', TotalWages));
  //reset variables
  TotalWages:= 0.00;
  TotalHours:= 0;
  TotalOverEightHours:= 0;
  TotalOverFortyHours:= 0;
  TotalSatHours:= 0;
  TotalSunHours:= 0;
  HourStr:= '';
  ArrayIndex:= 0;
  end; //while not EOF(F) do
  CloseFile(F);
 end
 else
 ShowMessage('File does not exist!');
end.

I'm sure there are many ways that this could have been written better. I really am just interested in why my values different from the expected values. Thanks!

Upvotes: 1

Views: 628

Answers (3)

David Heffernan
David Heffernan

Reputation: 612993

The code would benefit from the I/O and the calculation being separated. You problems are with the calculation. I'd write it something like this:

uses
  Math;

type
  TDay = (
    daySunday,
    dayMonday,
    dayTuesday,
    dayWednesday,
    dayThursday,
    dayFriday,
    daySaturday
  );
  TDayArray = array [TDay] of Integer;

function Wage(const Hours: TDayArray): Double;
const
  BasicRate = 10.0;
  DailyOvertimeRate = 1.5;
  WeeklyOvertimeRate = 2.5;
  DailyOvertimeThreshold = 8;
  WeeklyOvertimeThreshold = 40;
  DailyBonus: array [TDay] of Double = (1.5, 1.0, 1.0, 1.0, 1.0, 1.0, 2.25);
var
  Day: TDay;
  DailyOvertimeHours, WeeklyOvertimeHours, TotalHours: Double;
  DailyPay: array [TDay] of Double;
begin
  TotalHours := 0.0;
  for Day := low(Day) to high(Day) do begin
    TotalHours := TotalHours + Hours[Day];
    DailyOvertimeHours := Max(Hours[Day]-DailyOvertimeThreshold, 0.0);
    DailyPay[Day] := Hours[Day]*BasicRate;
    DailyPay[Day] := DailyPay[Day] + DailyOvertimeHours*DailyOvertimeRate;
    DailyPay[Day] := DailyPay[Day]*DailyBonus[Day];
  end;
  WeeklyOvertimeHours := Max(TotalHours-WeeklyOvertimeThreshold, 0.0);
  Result := Sum(DailyPay) + WeeklyOvertimeHours*WeeklyOvertimeRate;
end;

This is still a little unpolished and I'm not very happy with the variable names for pay rates, overtime etc.

Once have such a utility function available, then putting it together with the rest of your program becomes a lot easier.

The biggest weakness in your current program is that everything is housed in one giant routine. Break it down into small pieces and you'll be able to verify those small pieces more readily than hunting for problems in a single large routine.

Upvotes: 6

jasonpenny
jasonpenny

Reputation: 3039

For a simple problem like this, you might want to write it out by hand and then see if your code follows the same steps you did.

For Output 4, the 125% bonus for Saturday is not including the $1.50 per hour extra after 8:

she should earn

Wed: $103    | $100 for 10 hours plus $3 for 2 hours over 8
Thu: $103    | $100 for 10 hours plus $3 for 2 hours over 8
Fri: $103    | $100 for 10 hours plus $3 for 2 hours over 8
Sat: $231.75 | ($100 for 10 hours, $3 for 2 hours over 8), $128.75 for 125% bonus

for a total of 540.75

Upvotes: 6

jachguate
jachguate

Reputation: 17203

Find this by yourself by learning How to debug a Delphi program.

Pay atention to this parts:

Watches - you add a watch to track the values of program variables or expressions as you step over or trace into code.
Breakpoints - when pressing the F5 button or clicking on the left bar in your editor you can add a red line to your source. This line of source will have a breakpoint. When running the program, the execution will stop when it passes the source line. Now you can trace into your source by using some function keys.

Upvotes: 3

Related Questions