2

The aim of my programm is to show the salary for an Employee (Coder of Manager) depending of how many hours this employee worked in a month.The array containing 3 of employees go to Accountant as a parameter.Accountant return salary of every employee. Salary of Coder and of Manager is calculated in different ways.

Here is my Java code:

    public class OOP
    {  
       public static void main(String[] args)
       {  
    // fill the staff array with three Employee objects.


    Employee[] staff = new Employee[3];

    staff[0] = new Manager("Carl Cracker",75000.00,(short)160);
    staff[1] = new Coder("Harry Hacker", 50000.00,(short)165);
    staff[2] = new Coder("Tony Tester", 40000.00,(short)200);

    Accountant Counter = new Accountant();
    Counter.printSalary(staff, (byte)2);

       }
    }

    abstract class Employee
    {  
       public Employee(String n, double w, short h)
    {  
      name = n;

      wageRate = w;

      workedHours = h;

    }

     public String getName()
     {
         return name;
     }

     public double getSalary(short workingHours)
     {

        this.salary = this.wageRate * (this.workedHours/workingHours);
        return salary;
     }

     private String name;
     protected double wageRate;
     protected short workedHours;
     protected double salary;
    }
    class Coder extends Employee
    {
        public Coder (String n, double w, short h)
        {
            super( n,  w,  h);
        }

        public double getSalary(short workingHours)
        {
            return super.getSalary(workingHours);
        }
    }
    class  Manager extends Employee
    {
        public Manager (String n, double w, short h)
        {
            super( n,  w,  h);
        }
        public double getSalary(short workingHours)
        {
            if (workingHours > workedHours)
            return  super.getSalary(workingHours)*0.7;
            else
                {
                   salary = wageRate;
                   return salary;
                }


         }
     }
    class Accountant
    {
        public Accountant ()
        {
        }
        public void printSalary(Employee[] emp, byte monthInd)
        {
            Employee[] workers = emp;
            byte MID = monthInd;
            MID = (byte) (MID - 1);
            for (Employee worker : workers)
                {
                    System.out.printf("%s's salary this month is %8.2f",worker.getName(), worker.getSalary(workingHours[MID]));
                    System.out.println();
                }
        }

        private short[] workingHours = new short[]{168,160,160,172,162,154,184,168,168,184,168,172};
     }

Expected result:

Carl Cracker's salary this month is 75000

Harry Hacker's salary this month is 51562.5

Tony Tester's salary this month is 50000

Actual result:

Carl Cracker's salary this month is 75000,00

Harry Hacker's salary this month is 50000,00

Tony Tester's salary this month is 40000,00

Could please somebody explain me why?

ches
  • 21
  • 3
  • 2
    Just a note of caution, you should be extremely careful of using floating point numbers to represent currency, see the accepted answer to http://stackoverflow.com/questions/3730019/why-not-use-double-or-float-to-represent-currency for an explanation of why – Angelo Genovese Apr 24 '13 at 22:17
  • @AngeloGenovese I think a more concise warning is that you don't display them without rounding them first... – Ruan Mendes Apr 24 '13 at 22:38
  • 1
    @JuanMendes the errors can stack, with a large enough set of changes you could still lose a penny in some places. Personally I prefer to use either BigDecimal or an integer type holding the smallest significant value (cents for example), but that's a matter of opinion which is why I linked to the question which covers arguments for and against a range of solutions. – Angelo Genovese Apr 24 '13 at 23:59
  • @AngeloGenovese Agreed, I didn't think about imprecision added to imprecision – Ruan Mendes Apr 25 '13 at 00:08

1 Answers1

4

You are the victim of integer division in Java.

Even with short values, integer division (JLS 15.17.2) applies, where non-integer results are truncated. The second month, index 1, is 160 working hours. Tony Tester has 200 hours. In normal math, 200 / 160 = 1.25, but in Java integer division, 200 / 160 = 1. That's why you see 40000 instead of 50000.

In Employee's getSalary method, cast one of the values as a double to get floating-point division, so that the result is what you want.

this.salary = this.wageRate * ((double) this.workedHours/workingHours);

Your code's output:

$ java OOP
Carl Cracker's salary this month is 75000.00
Harry Hacker's salary this month is 50000.00
Tony Tester's salary this month is 40000.00

Changed code's output:

$ java OOP
Carl Cracker's salary this month is 75000.00
Harry Hacker's salary this month is 51562.50
Tony Tester's salary this month is 50000.00
rgettman
  • 176,041
  • 30
  • 275
  • 357
  • 2
    This is a correct and well-written answer and deserves some credit, especially when you consider the small effort that was given by the original poster to isolate the problem and post the minimum necessary code. Whoever downvoted it should explain how they justify marking it as "not useful." – erickson Apr 24 '13 at 22:15
  • @erickson I really think you should not be able to downvote without giving a reason, but users at meta don't think it's viable, as of now it's just common courtesy – Ruan Mendes Apr 24 '13 at 22:36