1

So far, this can read simpler decimal numbers like $10.00, $220.50, $14.25. But when it becomes numbers like $12.76, $320.84, $47.53, then it wouldn't even run.

I'm wondering what is causing it and how I can fix it.

This is the .h file

#define TWENTY_BILL 20.00
#define TEN_BILL 10.00
#define FIVE_BILL 5.00
#define ONE_BILL 1.00
#define QUARTER_COIN 0.25
#define DIME_COIN 0.10
#define NICKEL_COIN 0.05
#define PENNY_COIN 0.01

This is the .c file

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "Value.h"

int main(int argc, char *argv[] ) {

 /*
 *Checks if argc has just one argument
 *If not, give error message
 */
if (argc < 2) {
    printf("Error: One argument required.");
    return 0;//If more than 1 argument, stops it
}//end if

/*
 * Converts argv[1] into double input
 * Then input2 is created as a float
 * input is transferred to input2
 *  Floor function is used, Multiplies
 *  input2 by 100 and then divide by 100 to
 *  leave only 2 decimal places
 *  Then Prints input2, %6.2f sets the field width
 *  for 2 decimal places
 */
double input = atof(argv[1]);
float input2;
input2 = input;
input2 = floor(input2 * 100) / 100;
printf("You have entered: %6.2f\n", input2);

/*
 * Creates variables for dollar
 * bill and coin set to 0
 */
int twentycount = 0;
int tencount = 0;
int fivecount = 0;
int onecount = 0;
int quartercount = 0;
int dimecount = 0;
int nickelcount = 0;
int pennycount = 0;

//Loops when input is greater than 0.0
while (input2 > 0.0)
    {
        /*Twenty Dollar Bill
         * When $20 is less than input2,
         * input2 - $20 = new input2
         * Add count to twentycount
         */
        if (TWENTY_BILL <= input2)
        {
            input2 = input2 - TWENTY_BILL;
            twentycount++;
        }//end if twenty
        /************************/
        /*Ten Dollar Bill
         * When $10 is less than input2,
         * input2 - $10 = new input2
         * Add count to tencount
         */
        else if (TEN_BILL <= input2)
        {
            input2 = input2 - TEN_BILL;
            tencount++;
        }//end if ten
        /***********************/
        /*Five Dollar Bill
         * When $5 is less than input2,
         * input2 - $5 = new input2
         * Add count to fivecount
         */
        else if (FIVE_BILL <= input2)
        {
            input2 = input2 - FIVE_BILL;
            fivecount++;
        }//end if five
        /**********************/
        /*One Dollar Bill
         * When $1 is less than input2,
         * input2 - $1 = new input2
         * Add count to onecount
         */
        else if (ONE_BILL <= input2)
        {
            input2 = input2 - ONE_BILL;
            onecount++;
        }//end if one
        /*********************/
        /*Quarter Coin
         * When $0.25 is less than input2,
         * input2 - $0.25 = new input2
         * Add count to quartercount
         */
        else if (QUARTER_COIN <= input2)
        {
            input2 = input2 - QUARTER_COIN;
            quartercount++;
        }//end if quarter
        /*********************/
        /*Dime Coin
         * When $0.10 is less than input2,
         * input2 - $0.10 = new input2
         * Add count to dimecount
         */
        else if (DIME_COIN <= input2)
        {
            input2 = input2 - DIME_COIN;
            dimecount++;
        }//end if dime
        /*********************/
        /*Nickel Coin
         * When $0.05 is less than input2,
         * input2 - $0.05 = new input2
         * Add count to nickelcount
         */
        else if (NICKEL_COIN <= input2)
        {
            input2 = input2 - NICKEL_COIN;
            nickelcount++;
        }//end if nickel
        /*********************/
        /*Penny Coin
         * When $0.01 is less than input2,
         * input2 - $0.01 = new input2
         * Add count to pennycount
         */
        else if (PENNY_COIN <= input2)
        {
            input2 = input2 - PENNY_COIN;
            pennycount++;
        }//end if penny
        /********************/
        /*
         * If anything else
         * Print Invalid Change
         */
        else
        {
            printf("Invalid change");
        }

    }//end while loop

    /*
     * If twentycount is more than 0
     * Print amount of $20 bills used
     */
    if (twentycount > 0)
    {
        printf("Amount of $20: %i\n", twentycount);
    }//end twentycount
    /*
     * If tencount is more than 0
     * Print amount of $10 bills used
     */
    if (tencount > 0)
    {
        printf("Amount of $10: %i\n", tencount);
    }//end tencount
    /*
     * If fivecount is more than 0
     * Print amount of $5 bills used
     */
    if (fivecount > 0)
    {
        printf("Amount of $5: %i\n", fivecount);
    }//end fivecount
    /*
     * If onecount is more than 0
     * Print amount of $1 bills used
     */
    if (onecount > 0)
    {
        printf("Amount of $1: %i\n", onecount);
    }//end onecount
    /*
     * If quartercount is more than 0
     * Print amount of $0.25 bills used
     */
    if (quartercount > 0)
    {
        printf("Amount of $0.25: %i\n", quartercount);
    }//end quartercount
    /*
     * If dimecount is more than 0
     * Print amount of $0.10 bills used
     */
    if (dimecount > 0)
    {
        printf("Amount of $0.10: %i\n", dimecount);
    }//end dimecount
    /*
     * If nickelcount is more than 0
     * Print amount of $0.05 bills used
     */
    if (nickelcount > 0)
    {
        printf("Amount of $0.05: %i\n", nickelcount);
    }//end nickelcount
    /*
     * If pennycount is more than 0
     * Print amount of $0.01 bills used
     */
    if (pennycount > 0)
    {
        printf("Amount of $0.01: %i\n", pennycount);
    }//end pennycount


return 0;
}//end main
  • What does "wouldn't even run" mean? – lc. Feb 01 '13 at 06:59
  • Please be more specific, it doesn't run as in it crashes immediately? It never finishes? Something else entirely? – AnthonyM Feb 01 '13 at 07:05
  • well, I guess I used a wrong choice of words, I meant that there was nothing that is displayed – user2031589 Feb 01 '13 at 07:06
  • Try having it print out the value of input2 as it goes through the while loop (alternatively just use a debugger to check as it loops). This should help you find the point where it starts infinitely looping and from there you can either find a fix or edit your question to be very precise. – AnthonyM Feb 01 '13 at 07:10
  • Works for me, I tested it with [an online compiler](https://ideone.com/hDY5dV). I modified it to read the input from standard input because I can't pass a command line argument. You need to put a parameter on the command line when you run it, try *theprogram*.exe 64.25 – doug65536 Feb 01 '13 at 07:12
  • 1
    I suggest using integers that represent the number of cents. They're a lot easier to deal with. – chris Feb 01 '13 at 07:17
  • Wish I could, but for my assignment I have to use double. – user2031589 Feb 01 '13 at 07:26
  • And I found my problem, it's the penny loop that's not looping through, everything else can print except the penny. – user2031589 Feb 01 '13 at 07:28

3 Answers3

1

I think your problem lies with input2 > 0.0. Something like input2 >= 0.00001 would be better. This is because of the way floating points are represented in memory. (x+y) - x - y is not guaranteed to be = 0.

A simpler way would just be to convert the input to integer by multiplying by 100.

I also suggest you remove the while loop and replace all the if statements inside with while loops.

Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
0

I trust you have not covered structures yet. If you have, you need to revisit your code. In fact, you could improve things with arrays, but an array of structures would be better.

Remember that a binary floating point value cannot exactly represent most decimal values. Those such as 14.25 do have an exact binary representation, but 14.26 does not. (See also: C compiler bug (floating point arithmetic)? for the observations "10 * 0.1 is hardly ever 1.0" and "floating point numbers are like little piles of sand; every time you move one, you lose a little sand and gain a little dirt".)

You should convert the values to integer numbers of cents. You should also avoid float; use double, but use int in preference.

When I changed the code in the Invalid change clause to read:

        else
        {
            printf("Invalid change (%e)\n", input2);
            break;
        }

Then when I ran the program with the argument 14.26 and then with 14.48, I got the output:

$ ./change 14.26
You have entered:  14.26
Invalid change (2.288818e-07)
Amount of $10: 1
Amount of $1: 4
Amount of $0.25: 1
Amount of $0.01: 1
$ ./change 14.48
You have entered:  14.48
Invalid change (9.999549e-03)
Amount of $10: 1
Amount of $1: 4
Amount of $0.25: 1
Amount of $0.10: 2
Amount of $0.01: 2
$

Note that the error message includes a newline. The clause terminates the loop, too. I should probably set a flag to indicate that there was an error and suppress the output of the change. The calculation for 14.26 is correct but the calculation for 14.48 is a cent short. As you can see, my diagnostic prints the value that causes trouble so it is clear that there is a minuscule amount left over for 14.26, and just under one cent for 14.48.

Using an array and integers, you could write:

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

int main(int argc, char *argv[] )
{
    for (int n = 1; n < argc; n++)
    {
        double input = atof(argv[n]);
        int    cents = (100 * input + 0.5);
        printf("You have entered: %6d.%.2d\n", cents / 100, cents % 100);
        int denom[] = { 2000, 1000, 500, 100, 25, 10, 5, 1, 0 };

        for (int i = 0; denom[i] != 0 && cents > 0; i++)
        {
            if (cents >= denom[i])
            {
                int count = cents / denom[i];
                cents = cents - count * denom[i];
                printf("Amount of $%2d.%.2d: %i\n", denom[i] / 100, denom[i] % 100, count);
            }
        }
    }

    return 0;
}

Output:

$ ./change 14.48 14.26 14.47 14.31  14.00  20 10 5 1 0.25 0.10 0.05 0.01
You have entered:     14.48
Amount of $10.00: 1
Amount of $ 1.00: 4
Amount of $ 0.25: 1
Amount of $ 0.10: 2
Amount of $ 0.01: 3
You have entered:     14.26
Amount of $10.00: 1
Amount of $ 1.00: 4
Amount of $ 0.25: 1
Amount of $ 0.01: 1
You have entered:     14.47
Amount of $10.00: 1
Amount of $ 1.00: 4
Amount of $ 0.25: 1
Amount of $ 0.10: 2
Amount of $ 0.01: 2
You have entered:     14.31
Amount of $10.00: 1
Amount of $ 1.00: 4
Amount of $ 0.25: 1
Amount of $ 0.05: 1
Amount of $ 0.01: 1
You have entered:     14.00
Amount of $10.00: 1
Amount of $ 1.00: 4
You have entered:     20.00
Amount of $20.00: 1
You have entered:     10.00
Amount of $10.00: 1
You have entered:      5.00
Amount of $ 5.00: 1
You have entered:      1.00
Amount of $ 1.00: 1
You have entered:      0.25
Amount of $ 0.25: 1
You have entered:      0.10
Amount of $ 0.10: 1
You have entered:      0.05
Amount of $ 0.05: 1
You have entered:      0.01
Amount of $ 0.01: 1
$
Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

You have reached the place where floating point arithmetic is not quite like we thought in school. :-)

To compare input2 against zero, you’ll need to use an absolute epsilon, the value of which be some small multiple of FLT_EPSILON. This happens because floats/doubles cannot precisely represent all values, for instance double(.1) == 0.1000000000000000055511151231257827021181583404541015625. In order to account for this, you will need to decide when your number is "close enough" to zero.

Michael Foukarakis
  • 39,737
  • 6
  • 87
  • 123