Calculating the number of coins in money change Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)Money class for handling calculations with coinsFind Minimum Number of coinsMinimum number of coins to make changeCoin Change: Minimum number of coinsCalculating change in AdaConverting money into changeA program to represent a coin amount using the smallest number of coinsCalculating money made per hourCS50 Pset1 Greedy, change algorithmCreating change with the smallest number of coins

Do I really need recursive chmod to restrict access to a folder?

Why are there no cargo aircraft with "flying wing" design?

If a contract sometimes uses the wrong name, is it still valid?

How can I fade player when goes inside or outside of the area?

Why constant symbols in a language?

do i need a schengen visa for a direct flight to amsterdam?

What is this single-engine low-wing propeller plane?

What happens to sewage if there is no river near by?

Proof involving the spectral radius and the Jordan canonical form

Withdrew £2800, but only £2000 shows as withdrawn on online banking; what are my obligations?

What do you call a phrase that's not an idiom yet?

Are my PIs rude or am I just being too sensitive?

The logistics of corpse disposal

Why was the term "discrete" used in discrete logarithm?

Should I discuss the type of campaign with my players?

How to motivate offshore teams and trust them to deliver?

How do I stop a creek from eroding my steep embankment?

When is phishing education going too far?

Why is "Consequences inflicted." not a sentence?

Does surprise arrest existing movement?

How much radiation do nuclear physics experiments expose researchers to nowadays?

If 'B is more likely given A', then 'A is more likely given B'

What is a Meta algorithm?

Disable hyphenation for an entire paragraph



Calculating the number of coins in money change



Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)Money class for handling calculations with coinsFind Minimum Number of coinsMinimum number of coins to make changeCoin Change: Minimum number of coinsCalculating change in AdaConverting money into changeA program to represent a coin amount using the smallest number of coinsCalculating money made per hourCS50 Pset1 Greedy, change algorithmCreating change with the smallest number of coins



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








5












$begingroup$


I wrote a program that calculates the minimum number of coins required to give a user change.



One concern I have is: When do we initialize the value of a float to be negative or positive? I recently saw




float userInput = -1.0;



but what about




float userInput = 1.0;



Are there differences between the two, and when would one be used over the other?



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


int main(void)

float input = -1;
int z = 0;
int counter = 0;

do

printf("The amount of changed owed(in dollars) is ");
input = get_float();

while (input < 0);
input = input * 100;
input = round(input);
z = input;

while (z >= 25)

z = z - 25;
counter++;


while (z >= 10)

z = z - 10;
counter++;


while (z >= 5)

z = z - 5;
counter++;


while (z >= 1)

z = z-1;
counter++;


printf("The number of minimum coins needed is %dn", counter);











share|improve this question









New contributor




asimichroma is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$







  • 1




    $begingroup$
    The only missing thing is the #include lines at the top of the file. These are part of "the complete code". According to this site's guidelines, the question title should describe what your code is supposed to do, therefore "Calculating the number of coins in money change" is preferred.
    $endgroup$
    – Roland Illig
    yesterday






  • 2




    $begingroup$
    Oh I see, thank you! Is it okay now?
    $endgroup$
    – asimichroma
    yesterday






  • 1




    $begingroup$
    Thanks for all the edits. The cs50.h header already provides an important clue. :)
    $endgroup$
    – Roland Illig
    yesterday










  • $begingroup$
    No problem haha, thank you for letting me know :) Yes, I'm a newbie, sorry if my questions aren't worded the best way =p
    $endgroup$
    – asimichroma
    yesterday










  • $begingroup$
    No worries. It's almost impossible to get your first question perfect on the first try. As it is now, it's in the perfect state to be answered: It contains a compilable self-contained piece of code that can be generally reviewed, and a little bonus question on top of that.
    $endgroup$
    – Roland Illig
    yesterday

















5












$begingroup$


I wrote a program that calculates the minimum number of coins required to give a user change.



One concern I have is: When do we initialize the value of a float to be negative or positive? I recently saw




float userInput = -1.0;



but what about




float userInput = 1.0;



Are there differences between the two, and when would one be used over the other?



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


int main(void)

float input = -1;
int z = 0;
int counter = 0;

do

printf("The amount of changed owed(in dollars) is ");
input = get_float();

while (input < 0);
input = input * 100;
input = round(input);
z = input;

while (z >= 25)

z = z - 25;
counter++;


while (z >= 10)

z = z - 10;
counter++;


while (z >= 5)

z = z - 5;
counter++;


while (z >= 1)

z = z-1;
counter++;


printf("The number of minimum coins needed is %dn", counter);











share|improve this question









New contributor




asimichroma is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$







  • 1




    $begingroup$
    The only missing thing is the #include lines at the top of the file. These are part of "the complete code". According to this site's guidelines, the question title should describe what your code is supposed to do, therefore "Calculating the number of coins in money change" is preferred.
    $endgroup$
    – Roland Illig
    yesterday






  • 2




    $begingroup$
    Oh I see, thank you! Is it okay now?
    $endgroup$
    – asimichroma
    yesterday






  • 1




    $begingroup$
    Thanks for all the edits. The cs50.h header already provides an important clue. :)
    $endgroup$
    – Roland Illig
    yesterday










  • $begingroup$
    No problem haha, thank you for letting me know :) Yes, I'm a newbie, sorry if my questions aren't worded the best way =p
    $endgroup$
    – asimichroma
    yesterday










  • $begingroup$
    No worries. It's almost impossible to get your first question perfect on the first try. As it is now, it's in the perfect state to be answered: It contains a compilable self-contained piece of code that can be generally reviewed, and a little bonus question on top of that.
    $endgroup$
    – Roland Illig
    yesterday













5












5








5





$begingroup$


I wrote a program that calculates the minimum number of coins required to give a user change.



One concern I have is: When do we initialize the value of a float to be negative or positive? I recently saw




float userInput = -1.0;



but what about




float userInput = 1.0;



Are there differences between the two, and when would one be used over the other?



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


int main(void)

float input = -1;
int z = 0;
int counter = 0;

do

printf("The amount of changed owed(in dollars) is ");
input = get_float();

while (input < 0);
input = input * 100;
input = round(input);
z = input;

while (z >= 25)

z = z - 25;
counter++;


while (z >= 10)

z = z - 10;
counter++;


while (z >= 5)

z = z - 5;
counter++;


while (z >= 1)

z = z-1;
counter++;


printf("The number of minimum coins needed is %dn", counter);











share|improve this question









New contributor




asimichroma is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$




I wrote a program that calculates the minimum number of coins required to give a user change.



One concern I have is: When do we initialize the value of a float to be negative or positive? I recently saw




float userInput = -1.0;



but what about




float userInput = 1.0;



Are there differences between the two, and when would one be used over the other?



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


int main(void)

float input = -1;
int z = 0;
int counter = 0;

do

printf("The amount of changed owed(in dollars) is ");
input = get_float();

while (input < 0);
input = input * 100;
input = round(input);
z = input;

while (z >= 25)

z = z - 25;
counter++;


while (z >= 10)

z = z - 10;
counter++;


while (z >= 5)

z = z - 5;
counter++;


while (z >= 1)

z = z-1;
counter++;


printf("The number of minimum coins needed is %dn", counter);








beginner c homework floating-point change-making-problem






share|improve this question









New contributor




asimichroma is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




asimichroma is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited 15 hours ago









pacmaninbw

5,46821537




5,46821537






New contributor




asimichroma is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked yesterday









asimichromaasimichroma

286




286




New contributor




asimichroma is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





asimichroma is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






asimichroma is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







  • 1




    $begingroup$
    The only missing thing is the #include lines at the top of the file. These are part of "the complete code". According to this site's guidelines, the question title should describe what your code is supposed to do, therefore "Calculating the number of coins in money change" is preferred.
    $endgroup$
    – Roland Illig
    yesterday






  • 2




    $begingroup$
    Oh I see, thank you! Is it okay now?
    $endgroup$
    – asimichroma
    yesterday






  • 1




    $begingroup$
    Thanks for all the edits. The cs50.h header already provides an important clue. :)
    $endgroup$
    – Roland Illig
    yesterday










  • $begingroup$
    No problem haha, thank you for letting me know :) Yes, I'm a newbie, sorry if my questions aren't worded the best way =p
    $endgroup$
    – asimichroma
    yesterday










  • $begingroup$
    No worries. It's almost impossible to get your first question perfect on the first try. As it is now, it's in the perfect state to be answered: It contains a compilable self-contained piece of code that can be generally reviewed, and a little bonus question on top of that.
    $endgroup$
    – Roland Illig
    yesterday












  • 1




    $begingroup$
    The only missing thing is the #include lines at the top of the file. These are part of "the complete code". According to this site's guidelines, the question title should describe what your code is supposed to do, therefore "Calculating the number of coins in money change" is preferred.
    $endgroup$
    – Roland Illig
    yesterday






  • 2




    $begingroup$
    Oh I see, thank you! Is it okay now?
    $endgroup$
    – asimichroma
    yesterday






  • 1




    $begingroup$
    Thanks for all the edits. The cs50.h header already provides an important clue. :)
    $endgroup$
    – Roland Illig
    yesterday










  • $begingroup$
    No problem haha, thank you for letting me know :) Yes, I'm a newbie, sorry if my questions aren't worded the best way =p
    $endgroup$
    – asimichroma
    yesterday










  • $begingroup$
    No worries. It's almost impossible to get your first question perfect on the first try. As it is now, it's in the perfect state to be answered: It contains a compilable self-contained piece of code that can be generally reviewed, and a little bonus question on top of that.
    $endgroup$
    – Roland Illig
    yesterday







1




1




$begingroup$
The only missing thing is the #include lines at the top of the file. These are part of "the complete code". According to this site's guidelines, the question title should describe what your code is supposed to do, therefore "Calculating the number of coins in money change" is preferred.
$endgroup$
– Roland Illig
yesterday




$begingroup$
The only missing thing is the #include lines at the top of the file. These are part of "the complete code". According to this site's guidelines, the question title should describe what your code is supposed to do, therefore "Calculating the number of coins in money change" is preferred.
$endgroup$
– Roland Illig
yesterday




2




2




$begingroup$
Oh I see, thank you! Is it okay now?
$endgroup$
– asimichroma
yesterday




$begingroup$
Oh I see, thank you! Is it okay now?
$endgroup$
– asimichroma
yesterday




1




1




$begingroup$
Thanks for all the edits. The cs50.h header already provides an important clue. :)
$endgroup$
– Roland Illig
yesterday




$begingroup$
Thanks for all the edits. The cs50.h header already provides an important clue. :)
$endgroup$
– Roland Illig
yesterday












$begingroup$
No problem haha, thank you for letting me know :) Yes, I'm a newbie, sorry if my questions aren't worded the best way =p
$endgroup$
– asimichroma
yesterday




$begingroup$
No problem haha, thank you for letting me know :) Yes, I'm a newbie, sorry if my questions aren't worded the best way =p
$endgroup$
– asimichroma
yesterday












$begingroup$
No worries. It's almost impossible to get your first question perfect on the first try. As it is now, it's in the perfect state to be answered: It contains a compilable self-contained piece of code that can be generally reviewed, and a little bonus question on top of that.
$endgroup$
– Roland Illig
yesterday




$begingroup$
No worries. It's almost impossible to get your first question perfect on the first try. As it is now, it's in the perfect state to be answered: It contains a compilable self-contained piece of code that can be generally reviewed, and a little bonus question on top of that.
$endgroup$
– Roland Illig
yesterday










2 Answers
2






active

oldest

votes


















8












$begingroup$

In general we want to initialize a variable directly to the value it needs, rather than to a temporary "invalid" value. This reduces complexity, and helps to prevent the accidental use of the "invalid" value as if it were a real input.



We should also put variable declarations as close to the point of use as practical. (e.g. z could be declared at the point of assignment from input). It's best for variables to only exist in the scope in which they are needed.



Note that the input variable is effectively reassigned 3 times, and used to represent 3 different things in the program. If we split the program into separate stages, this becomes clearer:



int main(void)

float input = -1;

// here "input" is invalid - it's just a placeholder.

// get user input (dollars):

do

printf("The amount of changed owed(in dollars) is ");
input = get_float();

while (input < 0);


// here "input" is the amount of dollars as a float

// convert input to cents:

input = input * 100;
input = round(input);


// here "input" is the number of cents, as a float

// calculate number of coins for change:

int z = input; // note we actually want the number of cents as an int...
int counter = 0;

...

printf("The number of minimum coins needed is %dn", counter);




It's best to avoid reusing variables like this. Any name given to such a variable is inaccurate or very general (e.g. "input"). Also, when changing some part of the program, we have to understand and modify a much larger amount of code than would otherwise be necessary.



Here, we can avoid reusing the variable by splitting the program up using functions, e.g.:



float get_dollar_input()

while (true)

printf("The amount of change owed (in dollars) is: ");

const float dollars = get_float(); // variable initialized to actual value :)

if (dollars < 0)

printf("Input must not be negative.");
continue;


return dollars;



int convert_to_cents(float dollars)

return (int)round(dollars * 100);


int calculate_minimal_coins(int cents)

int counter = 0;

// ...

return counter;


int main(void)

const float dollars = get_dollar_input();
const int cents = convert_to_cents(dollars);
const int coins = calculate_minimal_coins(cents);

printf("The minimum number of coins needed is %dn", coins);




When calculating the change, we do a lot of subtraction in a loop. For a large input (e.g. $200,457,298.46), this could take a looooooong time. We can use division to find the count of each coin, and the remainder (modulus) operator to apply the subtraction:



int calculate_minimal_coins(int cents)

const int quarters = cents / 25;
cents %= 25;

const int dimes = cents / 10;
cents %= 10;

const int nickels = cents / 5;
cents %= 5;

const int pennies = cents; /* unnecessary, but explanatory */

return quarters + dimes + nickels + pennies;




One last thing: We should never use floating point variables to represent exact monetary values. It would be better to ask the user for the number of cents as an integer (or perhaps to ask for two integers: one for dollars, and one for cents).






share|improve this answer









$endgroup$








  • 1




    $begingroup$
    taking a floating point input and converting to int right away, as OP has done, is perfectly safe for amounts up to trillions of dollars (as far as floating-point precision is concerned - you can't actually store those amounts in a 32-bit int). Asking a user to enter monetary amounts in cents presents far more possibility of error.
    $endgroup$
    – Oh My Goodness
    yesterday











  • $begingroup$
    Using double instead of float would make this usage acceptable. The type float only guarantees 6 decimal places.
    $endgroup$
    – Roland Illig
    yesterday











  • $begingroup$
    200,457,298.46 converted to int cents overflow and is inaccurate with float anyways.
    $endgroup$
    – chux
    6 hours ago










  • $begingroup$
    Instead of int convert_to_cents(float dollars) return (int)round(dollars * 100); , consider long long convert_to_cents(double dollars) return llround(dollars * 100.0); `
    $endgroup$
    – chux
    6 hours ago


















3












$begingroup$


When do we initialize the value of a float to be negative or positive?




That's entirely use case dependent!



In your concrete example, initialisation is entirely irrelevant, as you overwrite the initialisation value anyway!



float input;

input = get_float();



Still initialising the variable might, though, prevent undefined behaviour if you later modify the code in a way the (re-)assignment might get skipped under some circumstances (you might forget to add the then necessary initialisation during modification...).



Back to the use cases: Even with same exponent and magnitude (i. e. with same absolute value) positive and negative are totally different values, consider pow(7.0, 10.12) and pow(7.0, -10.12) (whatever the values would mean) yielding totally different results (positive both times!), or consider results of sine and cosine.



Perhaps a bit more concrete: negative values in a banking application might mean you have some debts (although for such a scenario, I'd prefer integers with fixed point semantics, where number 1 would mean e. g. 1/100 or 1/1000 of a cent, whichever precision you might need).



If sign of numbers is irrelevant, prefer (well, there's no unsigned float/double...) positive ones, most people would consider them more natural – or would you prefer negative speed limit signs, meaning don't drive slower (i. e. smaller value -> higher absolute value) backwards?






share|improve this answer









$endgroup$













    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "196"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );






    asimichroma is a new contributor. Be nice, and check out our Code of Conduct.









    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f217425%2fcalculating-the-number-of-coins-in-money-change%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    8












    $begingroup$

    In general we want to initialize a variable directly to the value it needs, rather than to a temporary "invalid" value. This reduces complexity, and helps to prevent the accidental use of the "invalid" value as if it were a real input.



    We should also put variable declarations as close to the point of use as practical. (e.g. z could be declared at the point of assignment from input). It's best for variables to only exist in the scope in which they are needed.



    Note that the input variable is effectively reassigned 3 times, and used to represent 3 different things in the program. If we split the program into separate stages, this becomes clearer:



    int main(void)

    float input = -1;

    // here "input" is invalid - it's just a placeholder.

    // get user input (dollars):

    do

    printf("The amount of changed owed(in dollars) is ");
    input = get_float();

    while (input < 0);


    // here "input" is the amount of dollars as a float

    // convert input to cents:

    input = input * 100;
    input = round(input);


    // here "input" is the number of cents, as a float

    // calculate number of coins for change:

    int z = input; // note we actually want the number of cents as an int...
    int counter = 0;

    ...

    printf("The number of minimum coins needed is %dn", counter);




    It's best to avoid reusing variables like this. Any name given to such a variable is inaccurate or very general (e.g. "input"). Also, when changing some part of the program, we have to understand and modify a much larger amount of code than would otherwise be necessary.



    Here, we can avoid reusing the variable by splitting the program up using functions, e.g.:



    float get_dollar_input()

    while (true)

    printf("The amount of change owed (in dollars) is: ");

    const float dollars = get_float(); // variable initialized to actual value :)

    if (dollars < 0)

    printf("Input must not be negative.");
    continue;


    return dollars;



    int convert_to_cents(float dollars)

    return (int)round(dollars * 100);


    int calculate_minimal_coins(int cents)

    int counter = 0;

    // ...

    return counter;


    int main(void)

    const float dollars = get_dollar_input();
    const int cents = convert_to_cents(dollars);
    const int coins = calculate_minimal_coins(cents);

    printf("The minimum number of coins needed is %dn", coins);




    When calculating the change, we do a lot of subtraction in a loop. For a large input (e.g. $200,457,298.46), this could take a looooooong time. We can use division to find the count of each coin, and the remainder (modulus) operator to apply the subtraction:



    int calculate_minimal_coins(int cents)

    const int quarters = cents / 25;
    cents %= 25;

    const int dimes = cents / 10;
    cents %= 10;

    const int nickels = cents / 5;
    cents %= 5;

    const int pennies = cents; /* unnecessary, but explanatory */

    return quarters + dimes + nickels + pennies;




    One last thing: We should never use floating point variables to represent exact monetary values. It would be better to ask the user for the number of cents as an integer (or perhaps to ask for two integers: one for dollars, and one for cents).






    share|improve this answer









    $endgroup$








    • 1




      $begingroup$
      taking a floating point input and converting to int right away, as OP has done, is perfectly safe for amounts up to trillions of dollars (as far as floating-point precision is concerned - you can't actually store those amounts in a 32-bit int). Asking a user to enter monetary amounts in cents presents far more possibility of error.
      $endgroup$
      – Oh My Goodness
      yesterday











    • $begingroup$
      Using double instead of float would make this usage acceptable. The type float only guarantees 6 decimal places.
      $endgroup$
      – Roland Illig
      yesterday











    • $begingroup$
      200,457,298.46 converted to int cents overflow and is inaccurate with float anyways.
      $endgroup$
      – chux
      6 hours ago










    • $begingroup$
      Instead of int convert_to_cents(float dollars) return (int)round(dollars * 100); , consider long long convert_to_cents(double dollars) return llround(dollars * 100.0); `
      $endgroup$
      – chux
      6 hours ago















    8












    $begingroup$

    In general we want to initialize a variable directly to the value it needs, rather than to a temporary "invalid" value. This reduces complexity, and helps to prevent the accidental use of the "invalid" value as if it were a real input.



    We should also put variable declarations as close to the point of use as practical. (e.g. z could be declared at the point of assignment from input). It's best for variables to only exist in the scope in which they are needed.



    Note that the input variable is effectively reassigned 3 times, and used to represent 3 different things in the program. If we split the program into separate stages, this becomes clearer:



    int main(void)

    float input = -1;

    // here "input" is invalid - it's just a placeholder.

    // get user input (dollars):

    do

    printf("The amount of changed owed(in dollars) is ");
    input = get_float();

    while (input < 0);


    // here "input" is the amount of dollars as a float

    // convert input to cents:

    input = input * 100;
    input = round(input);


    // here "input" is the number of cents, as a float

    // calculate number of coins for change:

    int z = input; // note we actually want the number of cents as an int...
    int counter = 0;

    ...

    printf("The number of minimum coins needed is %dn", counter);




    It's best to avoid reusing variables like this. Any name given to such a variable is inaccurate or very general (e.g. "input"). Also, when changing some part of the program, we have to understand and modify a much larger amount of code than would otherwise be necessary.



    Here, we can avoid reusing the variable by splitting the program up using functions, e.g.:



    float get_dollar_input()

    while (true)

    printf("The amount of change owed (in dollars) is: ");

    const float dollars = get_float(); // variable initialized to actual value :)

    if (dollars < 0)

    printf("Input must not be negative.");
    continue;


    return dollars;



    int convert_to_cents(float dollars)

    return (int)round(dollars * 100);


    int calculate_minimal_coins(int cents)

    int counter = 0;

    // ...

    return counter;


    int main(void)

    const float dollars = get_dollar_input();
    const int cents = convert_to_cents(dollars);
    const int coins = calculate_minimal_coins(cents);

    printf("The minimum number of coins needed is %dn", coins);




    When calculating the change, we do a lot of subtraction in a loop. For a large input (e.g. $200,457,298.46), this could take a looooooong time. We can use division to find the count of each coin, and the remainder (modulus) operator to apply the subtraction:



    int calculate_minimal_coins(int cents)

    const int quarters = cents / 25;
    cents %= 25;

    const int dimes = cents / 10;
    cents %= 10;

    const int nickels = cents / 5;
    cents %= 5;

    const int pennies = cents; /* unnecessary, but explanatory */

    return quarters + dimes + nickels + pennies;




    One last thing: We should never use floating point variables to represent exact monetary values. It would be better to ask the user for the number of cents as an integer (or perhaps to ask for two integers: one for dollars, and one for cents).






    share|improve this answer









    $endgroup$








    • 1




      $begingroup$
      taking a floating point input and converting to int right away, as OP has done, is perfectly safe for amounts up to trillions of dollars (as far as floating-point precision is concerned - you can't actually store those amounts in a 32-bit int). Asking a user to enter monetary amounts in cents presents far more possibility of error.
      $endgroup$
      – Oh My Goodness
      yesterday











    • $begingroup$
      Using double instead of float would make this usage acceptable. The type float only guarantees 6 decimal places.
      $endgroup$
      – Roland Illig
      yesterday











    • $begingroup$
      200,457,298.46 converted to int cents overflow and is inaccurate with float anyways.
      $endgroup$
      – chux
      6 hours ago










    • $begingroup$
      Instead of int convert_to_cents(float dollars) return (int)round(dollars * 100); , consider long long convert_to_cents(double dollars) return llround(dollars * 100.0); `
      $endgroup$
      – chux
      6 hours ago













    8












    8








    8





    $begingroup$

    In general we want to initialize a variable directly to the value it needs, rather than to a temporary "invalid" value. This reduces complexity, and helps to prevent the accidental use of the "invalid" value as if it were a real input.



    We should also put variable declarations as close to the point of use as practical. (e.g. z could be declared at the point of assignment from input). It's best for variables to only exist in the scope in which they are needed.



    Note that the input variable is effectively reassigned 3 times, and used to represent 3 different things in the program. If we split the program into separate stages, this becomes clearer:



    int main(void)

    float input = -1;

    // here "input" is invalid - it's just a placeholder.

    // get user input (dollars):

    do

    printf("The amount of changed owed(in dollars) is ");
    input = get_float();

    while (input < 0);


    // here "input" is the amount of dollars as a float

    // convert input to cents:

    input = input * 100;
    input = round(input);


    // here "input" is the number of cents, as a float

    // calculate number of coins for change:

    int z = input; // note we actually want the number of cents as an int...
    int counter = 0;

    ...

    printf("The number of minimum coins needed is %dn", counter);




    It's best to avoid reusing variables like this. Any name given to such a variable is inaccurate or very general (e.g. "input"). Also, when changing some part of the program, we have to understand and modify a much larger amount of code than would otherwise be necessary.



    Here, we can avoid reusing the variable by splitting the program up using functions, e.g.:



    float get_dollar_input()

    while (true)

    printf("The amount of change owed (in dollars) is: ");

    const float dollars = get_float(); // variable initialized to actual value :)

    if (dollars < 0)

    printf("Input must not be negative.");
    continue;


    return dollars;



    int convert_to_cents(float dollars)

    return (int)round(dollars * 100);


    int calculate_minimal_coins(int cents)

    int counter = 0;

    // ...

    return counter;


    int main(void)

    const float dollars = get_dollar_input();
    const int cents = convert_to_cents(dollars);
    const int coins = calculate_minimal_coins(cents);

    printf("The minimum number of coins needed is %dn", coins);




    When calculating the change, we do a lot of subtraction in a loop. For a large input (e.g. $200,457,298.46), this could take a looooooong time. We can use division to find the count of each coin, and the remainder (modulus) operator to apply the subtraction:



    int calculate_minimal_coins(int cents)

    const int quarters = cents / 25;
    cents %= 25;

    const int dimes = cents / 10;
    cents %= 10;

    const int nickels = cents / 5;
    cents %= 5;

    const int pennies = cents; /* unnecessary, but explanatory */

    return quarters + dimes + nickels + pennies;




    One last thing: We should never use floating point variables to represent exact monetary values. It would be better to ask the user for the number of cents as an integer (or perhaps to ask for two integers: one for dollars, and one for cents).






    share|improve this answer









    $endgroup$



    In general we want to initialize a variable directly to the value it needs, rather than to a temporary "invalid" value. This reduces complexity, and helps to prevent the accidental use of the "invalid" value as if it were a real input.



    We should also put variable declarations as close to the point of use as practical. (e.g. z could be declared at the point of assignment from input). It's best for variables to only exist in the scope in which they are needed.



    Note that the input variable is effectively reassigned 3 times, and used to represent 3 different things in the program. If we split the program into separate stages, this becomes clearer:



    int main(void)

    float input = -1;

    // here "input" is invalid - it's just a placeholder.

    // get user input (dollars):

    do

    printf("The amount of changed owed(in dollars) is ");
    input = get_float();

    while (input < 0);


    // here "input" is the amount of dollars as a float

    // convert input to cents:

    input = input * 100;
    input = round(input);


    // here "input" is the number of cents, as a float

    // calculate number of coins for change:

    int z = input; // note we actually want the number of cents as an int...
    int counter = 0;

    ...

    printf("The number of minimum coins needed is %dn", counter);




    It's best to avoid reusing variables like this. Any name given to such a variable is inaccurate or very general (e.g. "input"). Also, when changing some part of the program, we have to understand and modify a much larger amount of code than would otherwise be necessary.



    Here, we can avoid reusing the variable by splitting the program up using functions, e.g.:



    float get_dollar_input()

    while (true)

    printf("The amount of change owed (in dollars) is: ");

    const float dollars = get_float(); // variable initialized to actual value :)

    if (dollars < 0)

    printf("Input must not be negative.");
    continue;


    return dollars;



    int convert_to_cents(float dollars)

    return (int)round(dollars * 100);


    int calculate_minimal_coins(int cents)

    int counter = 0;

    // ...

    return counter;


    int main(void)

    const float dollars = get_dollar_input();
    const int cents = convert_to_cents(dollars);
    const int coins = calculate_minimal_coins(cents);

    printf("The minimum number of coins needed is %dn", coins);




    When calculating the change, we do a lot of subtraction in a loop. For a large input (e.g. $200,457,298.46), this could take a looooooong time. We can use division to find the count of each coin, and the remainder (modulus) operator to apply the subtraction:



    int calculate_minimal_coins(int cents)

    const int quarters = cents / 25;
    cents %= 25;

    const int dimes = cents / 10;
    cents %= 10;

    const int nickels = cents / 5;
    cents %= 5;

    const int pennies = cents; /* unnecessary, but explanatory */

    return quarters + dimes + nickels + pennies;




    One last thing: We should never use floating point variables to represent exact monetary values. It would be better to ask the user for the number of cents as an integer (or perhaps to ask for two integers: one for dollars, and one for cents).







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered yesterday









    user673679user673679

    3,49811130




    3,49811130







    • 1




      $begingroup$
      taking a floating point input and converting to int right away, as OP has done, is perfectly safe for amounts up to trillions of dollars (as far as floating-point precision is concerned - you can't actually store those amounts in a 32-bit int). Asking a user to enter monetary amounts in cents presents far more possibility of error.
      $endgroup$
      – Oh My Goodness
      yesterday











    • $begingroup$
      Using double instead of float would make this usage acceptable. The type float only guarantees 6 decimal places.
      $endgroup$
      – Roland Illig
      yesterday











    • $begingroup$
      200,457,298.46 converted to int cents overflow and is inaccurate with float anyways.
      $endgroup$
      – chux
      6 hours ago










    • $begingroup$
      Instead of int convert_to_cents(float dollars) return (int)round(dollars * 100); , consider long long convert_to_cents(double dollars) return llround(dollars * 100.0); `
      $endgroup$
      – chux
      6 hours ago












    • 1




      $begingroup$
      taking a floating point input and converting to int right away, as OP has done, is perfectly safe for amounts up to trillions of dollars (as far as floating-point precision is concerned - you can't actually store those amounts in a 32-bit int). Asking a user to enter monetary amounts in cents presents far more possibility of error.
      $endgroup$
      – Oh My Goodness
      yesterday











    • $begingroup$
      Using double instead of float would make this usage acceptable. The type float only guarantees 6 decimal places.
      $endgroup$
      – Roland Illig
      yesterday











    • $begingroup$
      200,457,298.46 converted to int cents overflow and is inaccurate with float anyways.
      $endgroup$
      – chux
      6 hours ago










    • $begingroup$
      Instead of int convert_to_cents(float dollars) return (int)round(dollars * 100); , consider long long convert_to_cents(double dollars) return llround(dollars * 100.0); `
      $endgroup$
      – chux
      6 hours ago







    1




    1




    $begingroup$
    taking a floating point input and converting to int right away, as OP has done, is perfectly safe for amounts up to trillions of dollars (as far as floating-point precision is concerned - you can't actually store those amounts in a 32-bit int). Asking a user to enter monetary amounts in cents presents far more possibility of error.
    $endgroup$
    – Oh My Goodness
    yesterday





    $begingroup$
    taking a floating point input and converting to int right away, as OP has done, is perfectly safe for amounts up to trillions of dollars (as far as floating-point precision is concerned - you can't actually store those amounts in a 32-bit int). Asking a user to enter monetary amounts in cents presents far more possibility of error.
    $endgroup$
    – Oh My Goodness
    yesterday













    $begingroup$
    Using double instead of float would make this usage acceptable. The type float only guarantees 6 decimal places.
    $endgroup$
    – Roland Illig
    yesterday





    $begingroup$
    Using double instead of float would make this usage acceptable. The type float only guarantees 6 decimal places.
    $endgroup$
    – Roland Illig
    yesterday













    $begingroup$
    200,457,298.46 converted to int cents overflow and is inaccurate with float anyways.
    $endgroup$
    – chux
    6 hours ago




    $begingroup$
    200,457,298.46 converted to int cents overflow and is inaccurate with float anyways.
    $endgroup$
    – chux
    6 hours ago












    $begingroup$
    Instead of int convert_to_cents(float dollars) return (int)round(dollars * 100); , consider long long convert_to_cents(double dollars) return llround(dollars * 100.0); `
    $endgroup$
    – chux
    6 hours ago




    $begingroup$
    Instead of int convert_to_cents(float dollars) return (int)round(dollars * 100); , consider long long convert_to_cents(double dollars) return llround(dollars * 100.0); `
    $endgroup$
    – chux
    6 hours ago













    3












    $begingroup$


    When do we initialize the value of a float to be negative or positive?




    That's entirely use case dependent!



    In your concrete example, initialisation is entirely irrelevant, as you overwrite the initialisation value anyway!



    float input;

    input = get_float();



    Still initialising the variable might, though, prevent undefined behaviour if you later modify the code in a way the (re-)assignment might get skipped under some circumstances (you might forget to add the then necessary initialisation during modification...).



    Back to the use cases: Even with same exponent and magnitude (i. e. with same absolute value) positive and negative are totally different values, consider pow(7.0, 10.12) and pow(7.0, -10.12) (whatever the values would mean) yielding totally different results (positive both times!), or consider results of sine and cosine.



    Perhaps a bit more concrete: negative values in a banking application might mean you have some debts (although for such a scenario, I'd prefer integers with fixed point semantics, where number 1 would mean e. g. 1/100 or 1/1000 of a cent, whichever precision you might need).



    If sign of numbers is irrelevant, prefer (well, there's no unsigned float/double...) positive ones, most people would consider them more natural – or would you prefer negative speed limit signs, meaning don't drive slower (i. e. smaller value -> higher absolute value) backwards?






    share|improve this answer









    $endgroup$

















      3












      $begingroup$


      When do we initialize the value of a float to be negative or positive?




      That's entirely use case dependent!



      In your concrete example, initialisation is entirely irrelevant, as you overwrite the initialisation value anyway!



      float input;

      input = get_float();



      Still initialising the variable might, though, prevent undefined behaviour if you later modify the code in a way the (re-)assignment might get skipped under some circumstances (you might forget to add the then necessary initialisation during modification...).



      Back to the use cases: Even with same exponent and magnitude (i. e. with same absolute value) positive and negative are totally different values, consider pow(7.0, 10.12) and pow(7.0, -10.12) (whatever the values would mean) yielding totally different results (positive both times!), or consider results of sine and cosine.



      Perhaps a bit more concrete: negative values in a banking application might mean you have some debts (although for such a scenario, I'd prefer integers with fixed point semantics, where number 1 would mean e. g. 1/100 or 1/1000 of a cent, whichever precision you might need).



      If sign of numbers is irrelevant, prefer (well, there's no unsigned float/double...) positive ones, most people would consider them more natural – or would you prefer negative speed limit signs, meaning don't drive slower (i. e. smaller value -> higher absolute value) backwards?






      share|improve this answer









      $endgroup$















        3












        3








        3





        $begingroup$


        When do we initialize the value of a float to be negative or positive?




        That's entirely use case dependent!



        In your concrete example, initialisation is entirely irrelevant, as you overwrite the initialisation value anyway!



        float input;

        input = get_float();



        Still initialising the variable might, though, prevent undefined behaviour if you later modify the code in a way the (re-)assignment might get skipped under some circumstances (you might forget to add the then necessary initialisation during modification...).



        Back to the use cases: Even with same exponent and magnitude (i. e. with same absolute value) positive and negative are totally different values, consider pow(7.0, 10.12) and pow(7.0, -10.12) (whatever the values would mean) yielding totally different results (positive both times!), or consider results of sine and cosine.



        Perhaps a bit more concrete: negative values in a banking application might mean you have some debts (although for such a scenario, I'd prefer integers with fixed point semantics, where number 1 would mean e. g. 1/100 or 1/1000 of a cent, whichever precision you might need).



        If sign of numbers is irrelevant, prefer (well, there's no unsigned float/double...) positive ones, most people would consider them more natural – or would you prefer negative speed limit signs, meaning don't drive slower (i. e. smaller value -> higher absolute value) backwards?






        share|improve this answer









        $endgroup$




        When do we initialize the value of a float to be negative or positive?




        That's entirely use case dependent!



        In your concrete example, initialisation is entirely irrelevant, as you overwrite the initialisation value anyway!



        float input;

        input = get_float();



        Still initialising the variable might, though, prevent undefined behaviour if you later modify the code in a way the (re-)assignment might get skipped under some circumstances (you might forget to add the then necessary initialisation during modification...).



        Back to the use cases: Even with same exponent and magnitude (i. e. with same absolute value) positive and negative are totally different values, consider pow(7.0, 10.12) and pow(7.0, -10.12) (whatever the values would mean) yielding totally different results (positive both times!), or consider results of sine and cosine.



        Perhaps a bit more concrete: negative values in a banking application might mean you have some debts (although for such a scenario, I'd prefer integers with fixed point semantics, where number 1 would mean e. g. 1/100 or 1/1000 of a cent, whichever precision you might need).



        If sign of numbers is irrelevant, prefer (well, there's no unsigned float/double...) positive ones, most people would consider them more natural – or would you prefer negative speed limit signs, meaning don't drive slower (i. e. smaller value -> higher absolute value) backwards?







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered yesterday









        AconcaguaAconcagua

        34116




        34116




















            asimichroma is a new contributor. Be nice, and check out our Code of Conduct.









            draft saved

            draft discarded


















            asimichroma is a new contributor. Be nice, and check out our Code of Conduct.












            asimichroma is a new contributor. Be nice, and check out our Code of Conduct.











            asimichroma is a new contributor. Be nice, and check out our Code of Conduct.














            Thanks for contributing an answer to Code Review Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            Use MathJax to format equations. MathJax reference.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f217425%2fcalculating-the-number-of-coins-in-money-change%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Get product attribute by attribute group code in magento 2get product attribute by product attribute group in magento 2Magento 2 Log Bundle Product Data in List Page?How to get all product attribute of a attribute group of Default attribute set?Magento 2.1 Create a filter in the product grid by new attributeMagento 2 : Get Product Attribute values By GroupMagento 2 How to get all existing values for one attributeMagento 2 get custom attribute of a single product inside a pluginMagento 2.3 How to get all the Multi Source Inventory (MSI) locations collection in custom module?Magento2: how to develop rest API to get new productsGet product attribute by attribute group code ( [attribute_group_code] ) in magento 2

            Category:9 (number) SubcategoriesMedia in category "9 (number)"Navigation menuUpload mediaGND ID: 4485639-8Library of Congress authority ID: sh85091979ReasonatorScholiaStatistics

            Magento 2.3: How do i solve this, Not registered handle, on custom form?How can i rewrite TierPrice Block in Magento2magento 2 captcha not rendering if I override layout xmlmain.CRITICAL: Plugin class doesn't existMagento 2 : Problem while adding custom button order view page?Magento 2.2.5: Overriding Admin Controller sales/orderMagento 2.2.5: Add, Update and Delete existing products Custom OptionsMagento 2.3 : File Upload issue in UI Component FormMagento2 Not registered handleHow to configured Form Builder Js in my custom magento 2.3.0 module?Magento 2.3. How to create image upload field in an admin form