greedy algorithm (with coins) in C - c

In my code I usede the greedy algorithm in order to use the minimum amaount of coins. For example: I must return $0.41, the minimum amount of coins I can use is 4:
1 - 0,25;
1 - 0.10;
1 - 0.05;
1 - 0.01;
There are 4 types of coins: 0.25,0.10,0.05,0.01.
Here is my code:
#include <stdio.h>
#include <cs50.h>
int main(void)
{
printf("Enter the sum, that you want to return you:");
float sum = GetFloat();
float quaters = 0.25;
float dime = 0.10;
float nickel = 0.05;
float penny = 0.01;
int count_q = 0,count_d = 0,count_n = 0,count_p = 0;
while(sum<0){
printf("Incorrect, enter the positive float number");
sum = GetFloat();
}
while(sum > 0){
if(sum - quaters >=0){
sum -=quaters;
count_q +=1;
}
else if((sum -quaters <0) && (sum -dime>=0)){
sum -= dime;
count_d +=1;
}
else if((sum - dime <0) &&(sum - nickel>=0) ){
sum -= nickel;
count_n +=1;
}
else if(sum - nickel <0){
sum -= penny;
count_p +=1;
}
}
printf("The number of quaters: %i\n",count_q);
printf("The number of dimes: %i\n",count_d);
printf("The number of nickels: %i\n",count_n);
printf("The number of pennies: %i\n",count_p);
}
This code calculates how many coins of each type of was used to return the sum. In most cases it works fine.
But sometimes, for example, when i enter the number 1.12 it gives me wrong result:
Enter the sum, that you want to return you:1.12
The number of quaters: 4
The number of dimes: 1
The number of nickels: 0
The number of pennies: 3
I think, that the problem is in last else if statement. But i don't know how can I correct it.

To my understanding, there is no bug in your code in the strictest sense, as the reasoning on which the implementation is based (a greedy algorithm) is correct. You are most likely experiencing rounding errors due to repeated subtraction, as you use float, the single-precision floating type to represent your values. Perhaps, if you change float to double in your code, the output will be as expected for your example input.
However, this only pushes the boundaries of the limitation. Perhaps it would be better to internally represent the amount of money in pennies as int.
Note that, when first confronted with the fact that floating point representations are inaccurate, I believed that the impossibility to represent some values and accumulation of rounding errors would be an issue only when you absolutely do some rocket science calculations, but would never be relevant for what I considered to be layman's calculations. However, this is not the case.

Following up on what others have said, this will probably do the job: replace the variable declarations in your existing code with the below. The computation loop doesn't need to change since you wisely used named quantities rather than hard-coded constants.
float dollars = GetFloat();
int sum = (int)(dollars*100.0 + 0.5);
int quaters = 25;
int dime = 10;
int nickel = 5;
int penny = 1;
Edit:
The changes above have to be carried through wherever input happens. For example:
while(dollars<0){ /***/
printf("Incorrect, enter the positive float number");
dollars = GetFloat(); /***/
sum = (int)(dollars*100.0 + 0.5); /***/
}
printf("%d pennies\n", sum); /* For debugging */
I added the +0.5 to round-to-nearest rather than truncating - that might fix the 1.13 and 1.14 cases. If not, I would suggest seeing what your debugger tells you. If you are still stuck after that, please by all means post another question with your latest, updated code and test cases.

Related

While loop will not print the smallest number entered

I am creating a program that uses a while loop to provide multiple pieces of information from input given by the user. One of these pieces is the smallest number entered. I can't get it to print anything but 0. Any idea why?
#include <stdio.h>
#include <stdlib.h>
int main()
{
float num, sum = 0, sm, lg = 0, count = 0, avg = 0;
printf("Please enter a series of numbers (-1 to terminate): ");
scanf("%f", &num);
while(num > -1){
sum += num;
if(lg < num)
lg = num;
if(sm > num)
sm = num;
scanf("%f", &num);
count++;
avg = sum / count;
}
printf("The sum of your numbers is: %.4f\n", sum);
printf("You entered %.4f numbers\n", count);
printf("The average of the numbers you entered is: %.4f\n", avg);
printf("The smallest number you entered is: %.4f\n", sm);
printf("The Largest number you entered is: %.4f", lg);
return 0;
}
ex entry- 15
43
22.5
57.6
-1
Output-
sum:138.1000
4 numbers entered
average: 34.5250
smallest: 0.0000
Largest: 57.6000
In your code, sm has an undefined value because you aren't initializing it. You can initialize it to something like a very large number (or, even better, INFINITY) so it can be properly compared. The same goes for lg: if you want it to work for negative values too, you should initialize it with a very small value (-INFINITY). You can use INFINITY by including math.h.
the posted code does not compile!
first, because it is missing the needed #include statements for the needed header files. Specifically:
#include <stdio.h>
Then regarding this code block:
if(sm > num)
sm = num;
on the first pass through the while() loop, the variable sm is not initialized so accessing its' contents is undefined behavior.
Also, if using visual studio in debug mode, then all the stack is cleared to 0, so no other value will ever be assigned to it. This is why the algorithm always returns 0
Here's what I regard as a workable program. It uses double rather than float; if you insist, you can change the types and (input) formats to suit your desires. It has no particular limit on the number of rows it will accept. It doesn't output anything if there were no inputs. There is absolutely no need to use an array for the calculations. It uses use +∞ and -∞ to initialize the smallest (min) and largest (max) values respectively. Even if the only input is +∞ or -∞ (spelled +Inf or -Inf, or +Infinity or -Infinity, optionally without the + sign, and with upper-case, lower-case or mixed-case spelling) the correct values are produced.
#include <stdio.h>
#include <math.h>
int main(void)
{
double min = +INFINITY;
double max = -INFINITY;
double sum = 0.0;
size_t cnt = 0;
double value;
while (scanf("%lf", &value) == 1)
{
sum += value;
cnt++;
if (value > max)
max = value;
if (value < min)
min = value;
}
if (cnt > 0)
{
printf("Count = %zu\n", cnt);
printf("Sum = %g\n", sum);
printf("Min = %g\n", min);
printf("Max = %g\n", max);
printf("Average = %g\n", sum / cnt);
}
return 0;
}
Given ten random values between -1E6 and +1E6:
989375.672
-826955.668
224850.463
-401605.702
-45457.787
259618.099
821069.496
-268408.724
-512449.113
-46404.246
the program produces the output:
Count = 10
Sum = 193632
Min = -826956
Max = 989376
Average = 19363.2
I should probably put a bit more control on the output formatting, but the %g option is quite useful for numbers with wide ranges. Given the input data, using %11.3f would work well (it was used to format the output from the random number generator I used).

Greedy algorithm in C not returning any values?

I'm attempting to write a greedy algorithm with input that should return the smallest number of coins to be used in the change, but it's not returning any values. I am not sure why. It just asks for input, then displays nothing.
I made a previous thread where a bug was determined that resulted in an infinite loop, which was squashed, but now there seems to be another underlying bug in my logic.
#include <stdio.h>
#include <cs50.h>
#include <math.h>
// declare variable change_owed, num_coins, and input globally
float change_owed = 0;
float input;
int num_coins;
int main(void)
{
// makes sure the input is non-negative
do
{
input = get_float("Amount paid\n");
}
while(input <=0);
// begin checking
while(input > 0)
{
if(input - .25 >= 0) // quarters
{
num_coins++; // number of coins used, to be printed later, is incremented
input = input - .25; // coin is subtracted from total
}
if (input - .10 >= 0) // dimes
{
num_coins++;
input = input - .10;
}
if (input - .05 >= 0) // nickels
{
num_coins++;
input = input - .05;
}
if (input - .01 >= 0) // pennies
{
num_coins++;
input = input - .01;
}
}
printf("%i", num_coins);
}
In the commonly used format for double, .10 is not .10 but is 0.100000001490116119384765625. Also, you are using float variables (float input) with double constants (.10, .05, .01). At some point, your program has a remaining amount of money such as .00999…5 that is less than a penny, so it has no coin to subtract from it, so the code loops forever without subtracting anything. To fix that, as soon as you get the input, multiply it by 100, round it to the nearest integer (as with int cents = roundf(input * 100);), and use integer arithmetic for the rest of the calculations.
Once you have done that, your program will start producing results, and you will need to rethink the while and if structures you have, as mentioned in some of the comments.

show decimal using C

I'm trying to show the decimal points after the number
#include <stdio.h>
int main() {
int weight;
int miles;
int price;
printf("Enter the packages weight \n");
scanf("%d", &weight);
printf("Enter how many miles to ship the package \n");
scanf("%d", &miles);
if(weight <= 15) {
price = 15;
}
else {
price = (15 + ((weight - 15) * .5 ));
}
if(miles % 500 == 0) {
price += (miles / 500 * 10);
}
else {
price += ((miles / 500 )* 10) + 10;
}
printf("It will cost $%d to ship an item weighing %d pounds %d miles \n", price, weight, miles);
return 0;
}
for the price = (15+((weight-15)*.5)); When I plug in the numbers outside of the console it shows the decimal places. I'm probably missing the most simple thing...
You should change the data type of the variable price to float (or double) if you wish to store some fractional part in it.
Also, since miles / 500 may create some decimal part (and miles itself can be floating-point!), it should also be made float or double.
Finally, in the printf arguments, do not forget to change the format specifier %d.
Prefer to use a floating-point data type for all the variables involved in some computation that might yield fractional numbers as it will be more comprehensible and if you wish to not see the decimal part in the output, then set the precision to 0 (%.0f).

Trying to write a code for a bill changer/coin vending kiosk

I'm trying to write a code for a bill changer where the amount of money inserted are converted back into coins for the user. The problem is I keep having decimals in my amount of 50c like 222.222 when i input 111.111. My 20c and 10c is unused.. Please help
#include <stdio.h>
int main()
{
double sum50c=0, sum20c=0, sum10c=0, remainder, remainder2, remainder3, end=0;
double amount;
do
{
printf("Please enter an amount(dollars):");
scanf("%lf", &amount);
amount=amount*100;
if(amount<0){
printf("Invalid Input\n");
printf("Re-enter your amount:");
scanf("%lf", &amount);
}
if(amount>=50){
remainder=amount/50;
sum50c=remainder;
}else
if(remainder!=0){
remainder2=remainder/20;
sum20c=remainder2;
}else
if(remainder2!=0){
remainder3=remainder3/10;
sum10c=remainder3;
}
if(sum50c>200||sum20c>200||sum10c>200){
end++;
}else{
end=0;
}
}
while(end<=0);
printf("The amount of 50cents=%lf, 20cents=%lf, 10cents=%lf", sum50c, sum20c, sum10c);
}
There are basically two errors in your code:
Don't operate on floating-point numbers here. The number of coins will be a discrete number, which should be represented as int or maybe even unsigned int. The amount itself may be read in as floating-point number for simplicity, but it should also be converted to the number of cents as integerin order to avoid rounding errors.
You have to find combinations of coins: 30c is 1%times;20c + 1×10c. That means that you can't use else if chains, which will only consider one type of coin. Treat all types of coin, highes denomination first, and then reduce the amount still to handle. Note that with 10c as smallest coin, you might not be able to give full change for all amounts.
Here's you example without the outer loop and without the strange end business:
#include <stdlib.h>
#include <stdio.h>
int main()
{
int num50c = 0,
num20c = 0,
num10c = 0;
int amount; // amount in cents
double iamount; // input amount in dollars
printf("Please enter an amount: ");
scanf("%lf", &iamount);
amount = iamount * 100 + 0.5;
if (amount < 0) {
printf("Invalid Input\n");
exit(1);
}
num50c = amount / 50;
amount %= 50;
num20c = amount / 20;
amount %= 20;
num10c = amount / 10;
amount %= 10;
printf("%d x 50c = %d\n", num50c, num50c * 50);
printf("%d x 20c = %d\n", num20c, num20c * 20);
printf("%d x 10c = %d\n", num10c, num10c * 10);
printf("Remainder: %dc\n", amount);
return 0;
}
To force amount to have integer values you should round the value after your division:
if(amount>=50)
{
remainder=round(amount/50);
sum50c=remainder;
}

Why is my loop breaking early?

I am writing a function for class that takes an amount of money and tells the user how many coins add up to that amount. I seem to have everything working just fine, except pennies. My loop will sometimes stop short and break before adding the proper amount. It usually will stop 1 penny short, but sometimes it will give me the proper answer (one value I have found that gives the correct answer is .09). I've tried changing the float to a double, and I have the same issue. I am pulling my hair out trying to figure out what I am doing wrong.
void change(float total)
{
int quarters, dimes, nickels, pennies;
quarters = 0;
dimes = 0;
nickels = 0;
pennies = 0;
printf("\nTotal value entered: %.2f", total);
while (total >= .25)
{
quarters += 1;
total -= .25;
}
while (total >= .10)
{
dimes += 1;
total -= .10;
}
while (total >= .05)
{
nickels += 1;
total -= .05;
}
while (total >= .01)
{
pennies += 1;
total -= .01;
}
printf("\nQuarters: %d \nDimes: %d \nNickels: %d \nPennies: %d\n\n", quarters, dimes, nickels, pennies);
}
It's almost certainly caused by the limited precision of floating point numbers.
You'll probably find that you're reaching a point where the remaining value is something like 0.009999942 rather than 0.1 and that's why you're exiting early.
But it can show itself even before you reach pennies, if you end up with something like 0.249999 left, which should be a quarter but precision limits may force down to two dimes and four pennies.
As to solving it, I'd get the floating point value rounded to an integer as quickly as possible (multiplying it by a hundred beforehand of course), then you don't have to worry about floating point precision.
You can do this with something like:
int itotal = total * 100 + 0.2;
then using itotal for your calculations:
while (itotal >= 25) {
quarters++;
itotal -= 25;
}
// and so on ...
I had a similar question a while back for one of my labs. Instead of a a while loop for each coin denominations, i had a single do..while with cascaded if statements. In my case the max cost of an item was $1, and I opted to work in ints, but you can format the final output later.
int price, remainder, quarters, dime, nickel, pennies;
printf("Enter the price of the item you bought:>");
scanf("%d", &price);
remainder = 100 - price;
do {
if (remainder >= 25)
{
quarters++;
remainder -= 25;
}
else if (remainder >= 10)
{
dime++;
remainder -= 10;
}
else if (remainder >= 5)
{
nickel ++;
remainder -=5;
}
else if (remainder >= 1)
{
pennies ++;
remainder -=1;
}
} while (remainder > 0);
printf("\nYour change will be dispensed as:\n Quarters: %d \n Dimes: %d \n Nickel: %d \n Pennies: %d \n\n", quarters, dime, nickel,pennies);
Hope it helps.
Floating point math is not exact. See http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Floating point math is very complex and subject to many common mis expectations. Try converting your math to using int, and later translate it back.
As you are comparing float which subjected to be full of errors so you can use a roundof function and change the floating point number to integer.
int_total = round( total * 100.0 ); //include math.h
Now, change the loop as,
while (total >= 25)
{
quarters += 1;
total -= 25;
}

Resources