-1

New to programming. Taking class in C. Below is my attempt at a program that will print "What is your hourly wage?" then read the dollar.cent amount and calculate salary. Then print the salary in the form, "Your total income over a year is X dollars and Y cents.

To isolate dollars from the dollar.cent amount, I truncated the value by converting to an int from a double. I wasn't sure how to get the cents, so I figured I could subtract the dollars from the dollars.cents (*100) and I'd have the number of cents.

I run the program and it works fine, except I don't get the amount of cents I expect.

If the user enters 18.33 as the hourly wage. Then I get 31826 for total Dollars, 31836.40 for total Income. But when I subtract them and multiply by 100, I am given 39 cents instead of 40.

int main(void) {

double totalIncome       = 0.0;
int totalDollars         = 0;
int totalCents           = 0;
double hourlyWage        = 0.0;
int hoursPerWeek         = 40;
const int WEEKS_PER_YEAR = 52;

printf("What is your hourly wage? ");
scanf("%lf", &hourlyWage);

totalIncome = hourlyWage * hoursPerWeek * WEEKS_PER_YEAR;
totalDollars = totalIncome; //converts to int from double
totalCents = 10 * (totalIncome - totalDollars);

printf("Your total income over a year is %d dollars and %d cents", totalDollars, totalCents);

return 0;

}
  • 1
    If you compile with `-Wall`, do you get any warnings? I think that how you're assigning totalCents might lead to a loss of precision. But I'm not 100% sure. Compile with that flag, and check. – Ricky Mutschlechner Jan 17 '17 at 03:26
  • I came up with this hack solution... totalCents = ((totalIncome + 0.005) - totalDollars) * 100 ; – Alex Butterfield Jan 17 '17 at 03:30
  • I don't know what you mean by -Wall I'm verrrry new to this – Alex Butterfield Jan 17 '17 at 03:32
  • try totalCents = fmod(totalIncome, 10) – Sush Jan 17 '17 at 03:32
  • 3
    If you use GCC as your compiler, using `gcc -Wall …` will add a lot more helpful diagnostics, basically pointing out errors in your program that you should fix before running it. If you use `gcc -Wall -Werror …`, you'll have to fix them as they'll be errors, not warnings. If you're using MS Visual Studio, you should check whether you get better warnings if you use `cl /W3` — if not, check the manual. – Jonathan Leffler Jan 17 '17 at 03:34
  • @AlexButterfield `int totalCents = ((totalIncome + 0.005) - totalDollars) * 100` fails for many negative numbers and large numbers, fails for many edge conditions. Consider `totalIncome = 123.9999`. You idea will end up with 123 dollars and 100 cents. C has a good library in `` with many _round_ functions -use those – chux - Reinstate Monica Jan 17 '17 at 06:21

2 Answers2

4

The problem is that 100*(totalIncome - totalDollars) is not exactly 40, but 3.999999999941792e+01, thus casting it to int yields 39. This is a good example why one should never use floating points for computations with currencies.

BTW: You can simply avoid this issue altogether using something like scanf("%d.%d", &hourlyDollars, &hourlyCents);

cthl
  • 409
  • 2
  • 9
  • Love this solution, but if the user puts 10 as opposed to 10.00 what will happen there? Will this still work? – Alex Butterfield Jan 17 '17 at 06:01
  • Yes, it will actually just read 10 into `hourlyDollars`. However, this might not be the most reliable solution to cover all cases, but your initial solution did not perform any checks either. – cthl Jan 17 '17 at 06:23
1

To take a floating point money to floating point cents to the nearest whole number, use round() or rint()

double x;
double cents = rint(x * 100.0);

To take a floating point money to nearest integer cents, use lround() or llround()

long long cents = llround(x * 100.0);

To break into FP dollars into whole dollars and whole cents, scale, round and then separate.

double x;
double cents = rint(x * 100.0);
double cent =  fmod(cents, 100.0);
double dollar = (cents - cent)/100;

Avoid mixing types to support money. Use long long or double. Each has its short comings. For learner programs start with wide integer types of the smallest denomination (cents).

Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256