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)Find 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 coinsHow many ways we can make the change of the amount using the coins givenCalculating money made per hourCS50 Pset1 Greedy, change algorithmCreating change with the smallest number of coins
Slither Like a Snake
Is there a service that would inform me whenever a new direct route is scheduled from a given airport?
Why use gamma over alpha radiation?
Can a non-EU citizen traveling with me come with me through the EU passport line?
Simulating Exploding Dice
Autumning in love
How do I keep my slimes from escaping their pens?
Why is there no army of Iron-Mans in the MCU?
When communicating altitude with a '9' in it, should it be pronounced "nine hundred" or "niner hundred"?
How does modal jazz use chord progressions?
Do working physicists consider Newtonian mechanics to be "falsified"?
What can I do if my MacBook isn’t charging but already ran out?
What computer would be fastest for Mathematica Home Edition?
Is it possible to ask for a hotel room without minibar/extra services?
I'm having difficulty getting my players to do stuff in a sandbox campaign
Is above average number of years spent on PhD considered a red flag in future academia or industry positions?
How is simplicity better than precision and clarity in prose?
Can I throw a longsword at someone?
Strange behaviour of Check
How should I respond to a player wanting to catch a sword between their hands?
Why does tar appear to skip file contents when output file is /dev/null?
What did Darwin mean by 'squib' here?
What do you call the holes in a flute?
How can players take actions together that are impossible otherwise?
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)Find 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 coinsHow many ways we can make the change of the amount using the coins givenCalculating 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;
$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);
beginner c floating-point change-making-problem
New contributor
$endgroup$
add a comment |
$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);
beginner c floating-point change-making-problem
New contributor
$endgroup$
$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
22 hours ago
1
$begingroup$
Oh I see, thank you! Is it okay now?
$endgroup$
– asimichroma
22 hours ago
$begingroup$
Thanks for all the edits. Thecs50.h
header already provides an important clue. :)
$endgroup$
– Roland Illig
22 hours ago
$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
22 hours ago
$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
22 hours ago
add a comment |
$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);
beginner c floating-point change-making-problem
New contributor
$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 floating-point change-making-problem
beginner c floating-point change-making-problem
New contributor
New contributor
edited 13 hours ago
200_success
131k17157422
131k17157422
New contributor
asked 22 hours ago
asimichromaasimichroma
214
214
New contributor
New contributor
$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
22 hours ago
1
$begingroup$
Oh I see, thank you! Is it okay now?
$endgroup$
– asimichroma
22 hours ago
$begingroup$
Thanks for all the edits. Thecs50.h
header already provides an important clue. :)
$endgroup$
– Roland Illig
22 hours ago
$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
22 hours ago
$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
22 hours ago
add a comment |
$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
22 hours ago
1
$begingroup$
Oh I see, thank you! Is it okay now?
$endgroup$
– asimichroma
22 hours ago
$begingroup$
Thanks for all the edits. Thecs50.h
header already provides an important clue. :)
$endgroup$
– Roland Illig
22 hours ago
$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
22 hours ago
$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
22 hours ago
$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
22 hours ago
$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
22 hours ago
1
1
$begingroup$
Oh I see, thank you! Is it okay now?
$endgroup$
– asimichroma
22 hours ago
$begingroup$
Oh I see, thank you! Is it okay now?
$endgroup$
– asimichroma
22 hours ago
$begingroup$
Thanks for all the edits. The
cs50.h
header already provides an important clue. :)$endgroup$
– Roland Illig
22 hours ago
$begingroup$
Thanks for all the edits. The
cs50.h
header already provides an important clue. :)$endgroup$
– Roland Illig
22 hours ago
$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
22 hours ago
$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
22 hours ago
$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
22 hours ago
$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
22 hours ago
add a comment |
2 Answers
2
active
oldest
votes
$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).
$endgroup$
1
$begingroup$
taking a floating point input and converting toint
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
17 hours ago
$begingroup$
Usingdouble
instead offloat
would make this usage acceptable. The typefloat
only guarantees 6 decimal places.
$endgroup$
– Roland Illig
8 hours ago
add a comment |
$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?
$endgroup$
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
$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).
$endgroup$
1
$begingroup$
taking a floating point input and converting toint
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
17 hours ago
$begingroup$
Usingdouble
instead offloat
would make this usage acceptable. The typefloat
only guarantees 6 decimal places.
$endgroup$
– Roland Illig
8 hours ago
add a comment |
$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).
$endgroup$
1
$begingroup$
taking a floating point input and converting toint
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
17 hours ago
$begingroup$
Usingdouble
instead offloat
would make this usage acceptable. The typefloat
only guarantees 6 decimal places.
$endgroup$
– Roland Illig
8 hours ago
add a comment |
$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).
$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).
answered 18 hours ago
user673679user673679
3,45311130
3,45311130
1
$begingroup$
taking a floating point input and converting toint
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
17 hours ago
$begingroup$
Usingdouble
instead offloat
would make this usage acceptable. The typefloat
only guarantees 6 decimal places.
$endgroup$
– Roland Illig
8 hours ago
add a comment |
1
$begingroup$
taking a floating point input and converting toint
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
17 hours ago
$begingroup$
Usingdouble
instead offloat
would make this usage acceptable. The typefloat
only guarantees 6 decimal places.
$endgroup$
– Roland Illig
8 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
17 hours ago
$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
17 hours ago
$begingroup$
Using
double
instead of float
would make this usage acceptable. The type float
only guarantees 6 decimal places.$endgroup$
– Roland Illig
8 hours ago
$begingroup$
Using
double
instead of float
would make this usage acceptable. The type float
only guarantees 6 decimal places.$endgroup$
– Roland Illig
8 hours ago
add a comment |
$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?
$endgroup$
add a comment |
$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?
$endgroup$
add a comment |
$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?
$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?
answered 19 hours ago
AconcaguaAconcagua
32116
32116
add a comment |
add a comment |
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.
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
-beginner, c++, change-making-problem, floating-point
$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
22 hours ago
1
$begingroup$
Oh I see, thank you! Is it okay now?
$endgroup$
– asimichroma
22 hours ago
$begingroup$
Thanks for all the edits. The
cs50.h
header already provides an important clue. :)$endgroup$
– Roland Illig
22 hours ago
$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
22 hours ago
$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
22 hours ago