Home > Software design >  Amount of money represented by coins in C
Amount of money represented by coins in C

Time:01-12

My task is to write a program to represent an amount of money in different coins.

UPD: I'm allowed to use <stdio.h> only, modulo and division.

The output should be:

Coin     Qty   Balance
-------- --- ---------
              365.5700
Toonies  182    1.5700
Loonies    1    0.5700
Quarters   2    0.0700
Dimes      0    0.0700
Nickels    1    0.0200
Pennies    2    0.0000

But I'm getting this:

Coin     Qty   Balance
-------- --- ---------
              365.5700
Toonies  182    1.5700
Loonies    1    0.5700
Quarters   2    0.0600 
Dimes      0    0.0600 
Nickels    1    0.0100
Pennies    1    0.0000

This is my code. I cannot get the right calculations with quarters, dimes, nickels and pennies. What have I written wrong? Maybe the issue in type casting.

#include <stdio.h>

int main() {
    
    double total = 365.5700;
    
    int toonies, loonies, quarters, dimes, nickels, pennies;
    double balToonies, balLoonies, balQuarters, balDimes, balNickels, balPennines;
    
    // Toonies
    toonies = (int)total / 2;   
    balToonies = (int)(total * 100) % 200 / 100.0;
   
    // Loonies
    loonies = (int)balToonies / 1;
    balLoonies = (int)(balToonies * 100) % 100 / 100.0;
    
    // Quarters
    quarters = (int)(balLoonies * 100) / 25;
    balQuarters = (int)(balLoonies * 100) % 25 / 100.0;
   
    // Dimes
    dimes = (int)(balQuarters * 100) / 10;
    balDimes = (int)(balQuarters * 100) % 10 / 100.0;
    
    // Nickels
    nickels = (int)(balDimes * 100) / 5;
    balNickels = (int)(balDimes * 100) % 5 / 100.0;
    
    // Pennies
    pennies = (int)(balNickels * 100) / 1;
    balPennines = (int)(balNickels * 100) % 1 / 100.0;
   
    printf("Coin     Qty   Balance\n");
    printf("-------- --- ---------\n");
    printf("".4lf\n", total);
    printf("Toonies  = %9.4lf\n", toonies, balToonies);
    printf("Loonies  = %9.4lf\n", loonies, balLoonies);
    printf("Quarters = %9.4lf\n", quarters, balQuarters);
    printf("Dimes    = %9.4lf\n", dimes, balDimes);
    printf("Nickels  = %9.4lf\n", nickels, balNickels);
    printf("Pennies  = %9.4lf\n\n", pennies, balPennines);
    
    return 0;
}

CodePudding user response:

What have I written wrong?

Wrong use of floating point (FP) and integer math by not considering the roundings of FP math and integer truncation and their limitations of representable values.


When a FP result is just under a whole number, like x.99999..., applying (int) results in x instead of the desired x 1.

double cannot represent values like 365.5700 exactly. Instead a nearby value is used: 365.56999999999999317878973670303821563720703125. That is a whole number * some_power_of_2.

double * 100 often results in a rounded product.

These roundings and OP's casts which truncate result in various off-by-one calculations as compared to the desired result.

Alternative today

A simple alternative is to scale the money by the smallest unit, (which appears to be Can$0.0001 in this case) and use integer math.

Let's go with a wider type than int, so code can handle small accounts as well as large ones.

#include <math.h>

typedef long long ssymoney;
#define SSYMONEY_SCALE 10000
#define SSYMONEY_FROM_double(d) llround((d) * SSYMONEY_SCALE) 
#define SSYMONEY_TO_double(m) ((double)(m) / SSYMONEY_SCALE) 
#define SSYMONEY_TOONIE  (SSYMONEY_SCALE * 2) 
#define SSYMONEY_LOONIE  (SSYMONEY_SCALE * 1) 
#define SSYMONEY_QUARTER (SSYMONEY_SCALE * 25 / 100) 
#define SSYMONEY_DIME    (SSYMONEY_SCALE * 10 / 100) 
...


int main(void) {
    double total = 365.5700;
    ssymoney ssytotal = SSYMONEY_FROM_double(total);

    long long toonies, loonies, quarters, dimes, nickels, pennies;
    ssy_money balToonies, balLoonies, balQuarters, balDimes, balNickels, balPennines;

    // Toonies
    toonies = ssytotal / SSYMONEY_TOONIE;   
    balToonies = ssytotal % SSYMONEY_TOONIE ;

    // Loonies
    loonies = balToonies / SSYMONEY_LOONIE;   
    balLoonies = balToonies % SSYMONEY_LOONIE ;

    // quantity = balance / denomination
    // money balance_new = balance % denomination
    ...

    printf("".4lf\n", SSYMONEY_TO_double(ssytotal));
    printf("Toonies  %3lld %9.4lf\n", toonies, SSYMONEY_TO_double(balToonies));
    printf("Loonies  %3lld %9.4lf\n", loonies, SSYMONEY_TO_double(balLoonies));
    ...

Alternative later

The next version of C may support decimal floating point. Use that for money.

CodePudding user response:

You can use integer types.

int nominals[] = {100, 25, 10, 5, 1, 0};

void getNominals(double money, int *result)
{
    unsigned ncents = money * 100.0;
    int *nm = nominals;
    while(*nm && ncents)
    {
        *result   = ncents / *nm;
        ncents %= *nm  ;
    }
}

int main(void)
{
    int result[sizeof(nominals) / sizeof(nominals[0])] = {0};

    getNominals(4.36, result);

    for(size_t index = 0; nominals[index]; index  )
    {
        printf("%d = %d\n", nominals[index], result[index]);
    }
}

https://godbolt.org/z/3KKbfzh4z

CodePudding user response:

Thank you guys for your help! I have learned a lot. When I made this post I should have mentioned that I'm allowed only <stdio.h> library and no functions. I came up with this solution. Please let me know what do you think.

#include <stdio.h>

int main() {
  
  double total = 365.5700;
  
  int toonies, loonies, quarters, dimes, nickels, pennies;
    double balToonies, balLoonies, balQuarters, balDimes, balNickels, balPennines;
  
  // Toonies
    toonies = (int)total / 2;
    balToonies = (int)(total * 100   0.5) % 200 / 100.0;

    // Loonies
    loonies = (int)balToonies / 1;
    balLoonies = (int)(balToonies * 100   0.5) % 100 / 100.0;

    // Quarters
    quarters = (int)(balLoonies * 100) / 25;
    balQuarters = (int)(balLoonies * 100   0.5) % 25 / 100.0;

    // Dimes
    dimes = (int)(balQuarters * 100) / 10;
    balDimes = (int)(balQuarters * 100   0.5) % 10 / 100.0;

    // Nickels
    nickels = (int)(balDimes * 100) / 5;
    balNickels = (int)(balDimes * 100   0.5) % 5 / 100.0;

    // Pennies
    pennies = (int)(balNickels * 100);
    balPennines = (int)(balNickels * 100   0.5) % 1 / 100.0;

    printf("Sales INCLUDING tax\n");
    printf("Coin     Qty   Balance\n");
    printf("-------- --- ---------\n");
    printf("".4lf\n", total);
    printf("Toonies  = %9.4lf\n", toonies, balToonies);
    printf("Loonies  = %9.4lf\n", loonies, balLoonies);
    printf("Quarters = %9.4lf\n", quarters, balQuarters);
    printf("Dimes    = %9.4lf\n", dimes, balDimes);
    printf("Nickels  = %9.4lf\n", nickels, balNickels);
    printf("Pennies  = %9.4lf\n\n", pennies, balPennines);
   
    return 0;
}
  •  Tags:  
  • c
  • Related