Reputation: 3
Here's the program. It's meant to calculate an employee's net pay based on hours worked, hourly rate, tax withholds, etc. It calculates correctly, but the double-point precision formatting rounds the last decimal, losing the calculation's accuracy.
Sample Input:
Name: Smith
Hours worked this week: 10
Hourly rate: 6.75
Federal tax withhold: 20%
State tax withold: 9%
Output:
Summary
Employee: Smith
Gross Pay: 67.50
Federal Withholding: 13.50
State Withholding: 6.08
Total Deduction: 19.58
Net Pay: 47.93
import java.util.*;
public class Payroll
{
static Scanner key = new Scanner(System.in);
public Payroll()
{
System.out.print("Name: ");
String name = key.next();
System.out.print("Hours worked this week: ");
int hoursWorked = key.nextInt();
System.out.print("Hourly rate: ");
double payRate = key.nextDouble();
double payPreTax = hoursWorked * payRate;
System.out.print("Federal tax withhold: ");
String fedTaxStr = key.next().replace("%", "");
double fedTax = ((Double.parseDouble(fedTaxStr)) / 100) * payPreTax;
System.out.print("State tax withold: ");
String stateTaxStr = key.next().replace("%", "");
double stateTax = ((Double.parseDouble(stateTaxStr)) / 100) * payPreTax;
double amountWithheld = fedTax + stateTax;
double payPostTax = payPreTax - amountWithheld;
System.out.printf("\nSummary\n\nEmployee: " + name + "\nGross Pay: %.2f\nFederal Withholding: %.2f\nState Withholding: %.2f\nTotal Deduction: %.2f\nNet Pay: %.2f", payPreTax, fedTax, stateTax, amountWithheld, payPostTax);
}
public static void main(String[] args)
{
new Payroll();
}
}
Please have mercy; I'm first-year.
Upvotes: 0
Views: 116
Reputation: 718906
Preserving Accuracy When Formatting a Floating Point Number to Display With Two-point Precision
What you are asking for is self-contradictory / impossible.
You say:
It calculates correctly, but the double-point precision formatting rounds the last decimal, losing the calculation's accuracy.
That is correct. The floating point calculation will probably be accurate to at least 10 decimal points. As you note, the loss of accuracy (rounding) is actually happening when you format the number using %.2f
in the printf
call.
To put it simply, you cannot "preserve accuracy" and also print out the number with only 2 decimal points of precision.
The simple solution is to print with more digits after the decimal place; i.e. use a different format specifier for the number. (For instance ... %.4f
would give you 4 digits after the decimal point!)
I recommend that you read the javadocs for Formatter
which explains what format specifiers mean.
Actually, there is a second way of looking at this. You are using double
for your calculations here. A double
is a binary (base-2) floating point representation. Many decimal numbers cannot be represented precisely in binary floating point. (For the same reason that 1 / 3 is not precisely representable in decimal floating point.)
The normal way to deal with this in accounting software is to represent monetary values as integers (e.g. an integer number of cents) or a decimal floating-point representation. In Java BigDecimal
is the standard way to represent decimal floating point. It can cope with arbitrary precision.
Upvotes: 0