Check 50 Error in Cash App for CS50 Harvard - c

Very new to coding, so any help is appreciated, been stuck on these check errors for a while.
//source codde
#include <stdio.h>
#include <cs50.h>
#include <unistd.h>
int main(void)
{
float user;
int change, coins, decimals;
do
{
printf("Enter change amount\n");
user = get_float("");
} while (user <= 0);
change = user * 100;
coins = 0;
while (change >= 25)
{
change = change - 25;
coins++;
}
while (change >= 10)
{
change = change - 10;
coins++;
}
while (change >= 5)
{
change = change - 5;
coins++;
}
while (change >= 1)
{
change = change - 1;
coins++;
}
printf("You have entered\f%.1f\n", user);
sleep(1);
printf("The least amount of coins possible\f%.2d\n", coins);
}
Error messages that I keep getting:
:( input of 0.01 yields output of 1
expected "1\n", not "You have enter..." this actually returns back 01 so not sure
:( input of 1.6 yields output of 7
expected "7\n", not "You have enter..." same thing just 07 is there a way to remove the zero?
:( input of 4.2 yields output of 18
expected "18\n", not "You have enter..."
did you forget to round your input to the nearest cent?
This one I'm not sure it yields an output of 22

The reason you are seeing 22 rather than 18 for the input 4.20 is because of inexactness in floating point. Floats can not represent the value 4.20 exactly, so it will store a value slightly larger, or slightly smaller than 4.20 in your variable.
In the case that a slightly smaller value is used (for instance 4.1999999 or 4.19998567), when multiplying that with 100 you get something close to 419.99999. Turning that to an int will truncate that to 419 and give you the result of 22 coins.
The solution is to round to nearest integer, rather than truncating, when turning floats to integers. A common trick which works for small floats, is to add 0.5 before truncating:
change = user * 100 + 0.5;
Values in the range 419.5000 to 420.4999 will be turned into values in the range 420.0000 to 420.99999. And truncating will then produce 420.
You could naturally also use the builtin rounding functions that comes with c.
You should also consider using double rather than float. The space saved by using float is typically not worth it on modern desktop systems.

The problem set is very clear about what kind of output the program should deliver. You are not matching that. Read again.
And don't forget to round your input, as per problem set.

Related

Visual studio code bug

I was a writing a program to invert a 5 digit number in vs code and it goes like this:
// Program to reverse the number
#include <stdio.h>
#include <math.h>
int main()
{
int num, rev_num, a, temp,i;
printf("\nEnter the number to be reveresed: ");
scanf("%d", &num);
a = 0;
for (i = 4; i > (-1); i--)
{
temp = num % 10;
num = (num - temp) / 10;
a = a + temp * pow(10, i);
}
printf("\nThe reverse number is: %d",a);
return 0;
}
One of the input is here:
INPUT PIC
It yielded the output by subtracting 1 from the last digit. Similar is the case with other inputs too.
It yielded the correct output in all the c compilers except vs code. Is there some bug in the vs code or my program is wrong.
You are using a float function for integer purposes.
Getting an off-by-one problem is normal when doing so.
Compare Is floating point math broken?
The dirty details of floats where integers should be used can also easily explain differences between seemingly correct behaviour on one compiler and incorrect results on others.
So, assuming your question is "Is there some bug in the vs code[?] or my program is wrong[?]". I'd say there proabbly is a bug in VSCode (because I simply assume that for any larger program out there...), but not one explaining your observation. The problem is in your code.
In this case it would be easy to keep an increment (*10 instead of +1) number, which goes through values 1, 10, 100, 1000.
The point is to avoid floating points when the input, the output and the logic of the goal is integer.
Most elegantly (by which I mean with least changes to your code) this can be done by calculating a incrementally ("increment" by *10, not by +1). I.e. by multiplying by 10 each loop iteration.
I.e. instead of using pow(), to update a, do:
a = a*10 + temp;
This way, whatever is inside a at the start of the iteration (0 the first time) gets "moved to the left" and the 1-valued digit of the input number, which is found in temp is added.
Because of the way the integer / works you can also simplify the previous line to num = num / 10;, but that line as it is in your code also works fine.
This does not explicitly contain a variable which "increments" 1, 10, 100, it is more that a is going through temporary result values, which are in effect multiplied by 1, 10, 100, ... but the core of the idea is there and I think the minimal change to your code is an advantage of this solution.

While loop ignores a boolean expression which compares two floating point variables

Edit:I solved the issue by first multiplying the float value by 100, then rounding it with roundf() function, then casting it to an integer to be stored in an integer variable. I did the remaining operations with integer values from there on and everything worked. Even though the solution offered by #JacobBoertjes actually worked, my assignment requiered me to use get_float() from the cs50.h library, so I didn't implement it. Here's the final code:
// Get user input as a positive float value
float f_change;
do {
printf("Change owed: ");
f_change = get_float();
} while(f_change < 0);
// Round & cast
int int_change = (int) roundf(f_change * 100);
My program accepts an amount of money, say $4.20, and figures out the least amount of coins with which it can represent this value. For example, desired output from the program with $4.20 as an input would be: 16 quarters ($4.00), 2 dimes ($0.20).My program successfully calculates the number of quarters, but fails to do so while working on dimes. The cause of this failure is the second for loop in the code. 0.10 >= 0.10 does not evaluate to true, so the last iteration of the loop never happens. What am I doing wrong? Here is the code. I provided test print statements with their outputs written as comments.
#include <stdio.h>
#include <cs50.h>
int main(void) {
// Fake user input
float owed_coin = 4.2f;
// Initialize coin variables
int coin_count = 0;
float quarters = 0.25f,
dimes = 0.10f;
// Calculate quarters
while(owed_coin >= quarters) {
owed_coin -= quarters;
coin_count += 1;
}
printf("owed_coin: %.2f\ncoin_count: %d\n\n", owed_coin, coin_count);
// Prints owed_coin: 0.20
// coin_count: 16
// Calculate dimes
while(owed_coin >= dimes) {
owed_coin -= dimes;
coin_count += 1;
}
printf("owed_coin: %.2f\ncoin_count: %d\n\n", owed_coin, coin_count);
// Prints owed_coin: 0.10
// coin_count: 17
}
Floating point comparison is generally a bad idea because floats often become non-exact and thus will not be exactly equal. As #bruceg mentioned, a good solution is to keep your monetary values in terms of cents, so that you avoid using a float.
You could replace float owed_coin = 4.2f; with int owed_coin = 420;
In terms of gathering user input into this number, here is my suggestion using scanf
int n1, n2;
printf("Please enter amount:");
scanf("%d.%2d", &n1, &n2);
owed_coin = n1*100 + n2;
Another solution allows you you keep your variables as floats, and just compare for a very small difference between the two. It can be found here: What's wrong with using == to compare floats in Java?
It uses the Java Math library, but a similar solution could look something like this in C:
while((owed_coin - dimes) >= -0.001) {
owed_coin -= dimes;
coin_count += 1;
}
If you want to learn more about why floating point numbers suffer small innacuracies then check this out: https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems

CS50 greedy algorithm

I just started C programming with cs50.
I tried to do the problem set about the greedy algorithm but can't seem to find the bug. My code is below.
#include <cs50.h>
#include <stdio.h>
#include <math.h>
int main (void)
{
int count = 0;
printf("how much is the change?: ");
float change = get_float();
while(change < 0)
{
printf("change is to be more than 0");
change = get_float();
}
int amount = lroundf(change*100);
while(amount > 0)
{
if ((amount-25) >= 25)
{
amount = amount - 25;
count++;
}
else if ((amount-10) >= 10)
{
amount = amount - 10;
count++;
}
else if ((amount-5) >= 5)
{
amount = amount -5;
count++;
}
else if((amount-1) >= 1)
{
amount = amount -1;
count ++;
break;
}
else
{
printf("you have no change \n");
}
}
printf("your number of coins is %i\n", count);
}
When I input my change as 1, I am given back 8 coins. Can't seem to find where the bug is. Can anyone help me?
Firstly, you could try running your program with values for change that return simple answers, like 1 coin, using, for example, change = 0.25. If that works, then you should start trying with some few coins, repeating one type, like you did with 1.00, or joining a few types, like 0.06 . And after that, try big numbers and values with higher floating inaccuracy, like 4.10. Following this should lead you to your answers.
If, after trying that, you still can't find the problem, then here is the answer: the problem is with the if/else if expressions. When you are trying to count the quarters, for example, the (amount-25) >= 25 doesn't work properly. You're trying to take away a quarter while amount is bigger or equal to 25, but your code just do that until it gets to less than 50. Developing your expression may help you see it: (amount-25) >= 25 -> (amount-25) + 25 >= 25 + 25 -> amount >= 50.
Another problem you may find is with that break statement. It might get out from the loop earlier than expected. If you try running numbers like 0.04 and 0.03 you'll see the count stuck at 1. After removing the first penny, the code breaks out of the loop leaving amount still bigger than 0. breaks make it harder to see when the code is getting out of the loop and that's why many programmers recommend avoiding it whenever possible.

Why do I lose the remainder of a value after performing arithmetic in C?

I am trying to learn basic C programming by following a textbook and I must be missing something about either the data types, rounding, and/or order of operations because when I try to construct a simple program to convert seconds to hours and minutes, the hours work but the remaining minutes come out to 0 when they should not be.
Thanks to Coursera, I am aware that there are huge security vulnerabilities with programs like this, but for learning purposes I'll ask you to ignore security. For now, the books wants me to stick to using printf, scanf, and a while loop as they correspond to the chapters of the textbook I'm reading (the books lets me know that I'll get to start worrying about security when I'm a few chapters further along).
My C program looks like this:
/* Ask the user for a number of seconds, convert to X hours and Y minutes */
/* Continue doing this with a while loop until user enters 0 */
#include <stdio.h>
#include <conio.h>
#include <string.h>
int main(void)
{
const int minperhour = 60;
const int secpermin = 60;
int sec, hr;
float min;
sec = 1;
while(sec != 0)
{
printf("Enter the number of seconds to convert: \n");
scanf("%i", &sec);
min = sec/secpermin;
hr = min/minperhour;
min = (sec/secpermin) - (hr * minperhour);
printf("%d hours and %f minutes \n", hr, min);
}
return 0;
}
I would expect that I could enter 3601 and the result would be:
1 hours and 0.01667 minutes
because this is how the expression is evaluated in the R language, with which I'm more familiar:
> min = 3601/60
> min
[1] 60.02
> hr = min/60
> hr
[1] 1
> min = (3601/60) - (1 * 60)
> min
[1] 0.01667
However, what I get in C is this:
C:\Users\hackr>pa2q3.exe
Enter the number of seconds to convert:
3601
1 hours and 0.000000 minutes
Enter the number of seconds to convert:
7205
2 hours and 0.000000 minutes
Enter the number of seconds to convert:
0
0 hours and 0.000000 minutes
C:\Users\hackr>
I threw in the 7205 second attempt just for good measure.
I have a feeling that some of the you C gurus on Stack Overflow could use more advanced techniques to write a secure version of the program in some more succinct form. This may be educational as well if you want to mention it, but first and foremost I need to understand what's going on with this simple program.
Integer division: the integer value after dividing two ints gets stored in a floating point format. Eg:
float a = 3/5;
here an integer division will occur between 3 and 5 resulting in 0. Now, if you try to store this 0 in a float variable, it will be stored as 0.00.
min = sec/secpermin;
Should be
min = (float)sec/secpermin;
or
min = sec/(float)secpermin;
or, as #alk pointed out, you could also do this instead:
min = sec;
min /= secpermin; // min=min/secpermin; here, typecasting is not required as
// numerator (min) is already float.
Alternatively, you can make them all float, and while printing typecast them as int.

Casting an int into a float results in an incorrect value (not the usual decimal rounding error though)

For some reason I am getting some very unexpected results when converting an integer in to a float (using c(-ish) on Arduino).
In the past I have had problems with memory on the arduino so that may be either a helpful troubleshooting hint or a red herring.... you're pick.
Anyways, here is my code (only the relevant parts), and the value that is given is "6/8" which should result in meterValue = 0.75:
My function:
int getIntegerFromFileStream(File f, char* previewedChar) {
int num = 0;
while (48 <= *previewedChar && *previewedChar <= 57) {
// Ascii range 48-57 represents digits 0-9
num = (num*10) + atoi(previewedChar);
*previewedChar = f.read();
}
Serial.print(F("Found integer: "));
Serial.println(num);
}
Main code:
[.... rest of my code ....]
// Get the value for the meter from the fractional form (ex: 4/4 or 6/8)
meterValue = (float)getIntegerFromFileStream(file, &inputChar);
Serial.print(F("New meter value: "));
Serial.println(meterValue);
if (inputChar == '/') {
inputChar = file.read(); // move past the '/'
meterValue /= (float)getIntegerFromFileStream(file, &inputChar);
Serial.print(F("New meter value: "));
Serial.println(meterValue);
}
[.... rest of my code ....]
And here is the output from the above code:
Found integer: 6
New meter value: 3.00
Found integer: 8
New meter value: 1.00
New meter value: 1.00
As you can see from the output, the integer itself is being parsed correctly, but once it leaves the function and is casted to a float, its value changes (and not in the usual float-decimal-error way).
Any tips would be appreciated!
Edit:
Found my newb mistake: i don't have a return value for my getInt function, so it was resulting in undefined behaviour.
Turns out that, by default, Arduino does not give warnings during compilation unless you specifically go in to Preferences and turn on 'verbose' output for compilation. Once that was set I was able to see these kinds of warnings.
(this is only edited in for now because I'm too new to stackoverflow to answer my own question yet, i'll do so once my time limit is up)
Found my newb mistake: i don't have a return value for my getInt function, so it was resulting in undefined behaviour.
Turns out that, by default, Arduino does not give warnings during compilation unless you specifically go in to Preferences and turn on 'verbose' output for compilation. Once that was set I was able to see these kinds of warnings.

Resources