Wrong calculation for decimal amount in C language - c

I'm trying to calculate the decimal amount in float but it won't calculate if the input is "0.01". However, it will calculate if the input is "0.02" but with wrong calculation. Here is the code:
#include <stdio.h>
#include <cs50.h>
float MCounting = 0.00;
int MAmountCoin = 0;
float MAmountUsed = 0.00;
int MCoinCount = 0;
float MRemainAmount = 0;
int MCoinOut = 0;
int MTotCoinOut = 0;
int main(void)
{
float Amount;
float MRemainAmount;
do
{
printf("Specify the amount you want in change: ");
Amount = GetFloat();
MRemainAmount = Amount;
}
while (Amount < 0 );
if (MRemainAmount > 0 || MRemainAmount < .05 )
printf ("\n\n ***** Calculatin for 0.01 *****\n");
{
printf ("MRemainAmount Before calculation: %.2f\n",MRemainAmount);
MCoinOut = MRemainAmount / .01;
printf ("MCoinOut = %i...MTotCoinOut = %i\n",MCoinOut,MTotCoinOut);
MRemainAmount = MRemainAmount - (MCoinOut * .01);
printf ("MRemainAmount = %.2f\n",MRemainAmount);
MTotCoinOut = MCoinOut + MTotCoinOut;
printf ("MTotCoinOut = %i\n",MTotCoinOut);
}
{ printf("Total Coin Out%i\n",MTotCoinOut); }
}
What's going wrong and how can I fix it?

You are hitting your epsilon limit. Since you are using floats you are limited in representation by FLT_EPSILON; if you were using a double, you would see improved resolution of DBL_EPSILON. (These values are from <float.h>)
#define DBL_EPSILON 2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */
#define FLT_EPSILON 1.192092896e-07F /* smallest such that 1.0+FLT_EPSILON != 1.0 */
Thus if you are using a value like 10000, roughly, you're smallest change in value is something in the vicinity of 10000 * FLT_EPSILON, which would be about .012. If you want to represent with better precision, use doubles.

It is due to the imprecise representation of floating point numbers in the computers memory.
Read up on http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

Related

Logarithm calculator

I'm trying to make a logarithm calculator and got stuckā€”it doesn't print out a value. The problem may be at lines 15 or 24 or both. How can I make it print the value (all written in C).
Here's the full code:
#include <stdio.h>
#include <stdlib.h>
// Finds base 10 logarithms
int main()
{
float result;
float base = 10.0;
float multiplier = 1.0;
// float counter1 = 0.0;
// float counter2 = 0;
printf("Input result: ");
scanf("%l", result);
// Solves for all results above the base
if(result > base) {
while(result > multiplier) {
multiplier = multiplier * multiplier; // the multiplier has to check non-whole numbers
multiplier += 0.001;
} // division
}
printf("Your exponent is: %l \n", &multiplier);
printf("Hello mathematics!");
return 0;
}
All help appreciated,
Xebiq
you should delete & in printf,and add & in scanf.
printf("Your exponent is: %f \n", multiplier);
scanf("%f", &result);
and use %f in them.
and with base 10 I suggest this function to calculate log:
unsigned int Log2n(unsigned int n)
{
return (n > 1) ? 1 + Log2n(n / 10) : 0;
}
also you should know about Floating-point numbers here:
multiplier += 0.001;
probably exactly 0.001 won't be added to multiplier when I debugged this 0.00100005 was being add to multiplier in my compiler.(which will affect multiplying)
In printf remove '&' and in scanf add '&' before variable.

Why is average calculating program showing different results after decimal points?

**While runnning the C program the output is 33.000
Meanwhile the correct answer is 33.200
what is wrong is there any data return type issue with float,
so Should I use double data type I getting i head stuck **
#include <stdio.h>
float passingmarksArrray(int studentmarks[5]);
int main(){
float studentmarks_Average ;
int marks[5] = {21, 24, 32, 45, 44};
studentmarks_Average = passingmarksArrray(marks);
printf("The average marks of the student is %.3f \n", studentmarks_Average );
return 0;
}
float passingmarksArrray(int studentmarks[5]){
int i;
int sumofmarks = 0;
float average;
for (int i = 0; i < 5; ++i)
{
sumofmarks = sumofmarks + studentmarks[i];
}
average = (sumofmarks / 5) ;
return average;
}
The problem is, the statement
(sumofmarks / 5) ;
is an integer division, which will not yield a floating point result. To obtain a floating point result, you need to enforce floating point division, by saying
(sumofmarks / (float)5) ;
or
(sumofmarks / 5.0) ;
In the expression (average = (sumofmarks / 5))
sumofmarks / 5 returns an integer value which is then converted to float and stored in average.
while sumofmarks / 5.0 returns float value.

I wrote a program to print all primes number up-to a given a number

#include<stdio.h>
float abso(float a)
{
if(a<0.0)
return(-1*a);
else
return a;
}
int sqert(int x)
{
float x1 = (float)x;
float g1, g2;
g1 = x1/2.0;
g2 = x1/g1;
double e=0.000000001;
int sr;
while(abso(g1-g2)>=e)
{
g2 = (g1+x1/g1)/2.0;
g1 = x1/g2;
}
sr = (int)g1;
return(sr);
}
int main()
{
int num;
//num = 0;
printf("Enter a num between 1 and 1000 ");
scanf("%d",&num);
//printf("hello");
int flag;
flag = 0;
int i;
i = 2;
int m, j;
m = j = 0;
while(i<=num)
{
flag = 1;
if(i==2)
{
printf("%d ",i);
i++;
}
else if(i==3)
{
printf("%d ",i);
i= i+2;
}
else if(i>3)
{
m = sqert(i);
for(j=2;j<=m;j++)
{
if((i%j) == 0)
{
flag = 0;
break;
}
}
if(flag == 0)
{
i = i + 2;
continue;
}
if(j==m+1)
printf("%d ",i);
i = i + 2;
}
}
printf("\n");
return(0);
}
Here sqert function is taking square root of the input value and abso function is taking the absoulte value of given value.
The logic used is simple we are iterating to the square root of that number and then check for every number if it is divisible by any other number than itself then it is not a prime number else it is a prime number.
But this program is working only for value upto 5. After that it is not printing anything. It is not printing the entered number also.
Any help would be appreciated.
In your code, you are trying to compare float with double.
while(abso(g1-g2)>=e)
This is not correct because of the difference in precision between float and double.
double has 2 times more precision than float.
float is a 32 bit IEEE 754 single precision floating point number
(1 bit for the sign, 8 bits for the exponent, and 23* for the value),
i.e. float has 7 decimal digits of precision.
double is a 64 bit IEEE 754 double precision floating point number
(1 bit for the sign, 11 bits for the exponent, and 52* bits for the value),
i.e. double has 15 decimal digits of precision.
Declare e as float and make sure it is assigned a value that fits with the precision of float.
Something like:
float e = 0.00001;
Then your code will work as intended.
#EricPostpischil in the comments said that the sqert function may not always return the correct approximation. This is correct.
So it is better to use sqrt from math.h which works perfectly instead of sqert.

Integer overflow in greedy coin counting

#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main (void) {
printf ("Enter amount: ");
float amount = GetFloat();
int coins = 0;
while (amount != 0) {
if (fmod(amount, 0.25) == 0) {
amount = amount - 0.25;
coins += 1;
}
else if (fmod(amount, 0.10) == 0) {
amount = amount - 0.10;
coins += 1;
}
else if (fmod(amount, 0.05) == 0) {
amount = amount - 0.05;
coins += 1;
}
else {
amount = amount - 0.01;
coins += 1;
}
}
printf ("Coins : %d\n", coins);
}
I'm trying to implement a small greedy algorithm, in which a user inputs an amount of money ( Ex: 9.25 ) and we output the least amount of coins that it takes for us to exchange it in change( 25 cents, 10 cents, 5 cents and 1 cent only).
This algorithm works with int amounts like 10 or 20 and with amounts that only requires the program to use the 25 cents coins.
If I try an amount like 9.10 or 9.01, I get a runtime error, signed integer overflow. I understand what it means, but I don't understand how can the value of coins go so high all of a sudden.
As Danial Tran said it is better to use int when you do logical operations. Please read Why not use Double or Float to represent currency? Also you can avoid while loop.
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main (void) {
printf ("Enter amount: ");
//float amount = GetFloat(); //Please refer to chqrlie's comments below.
double amount = 0.0;
scanf("%lf",&amount); //I don't know GetFloat() equivalent for double. So using scanf().
long long int amountInt = (long long int) (amount * 100.0);
int coins = 0;
if (25 <= amountInt) {
coins += (amountInt/25);
amountInt = amountInt % 25;
}
if (10 <= amountInt) {
coins += (amountInt/10);
amountInt = amountInt % 10;
}
if (5 <= amountInt) {
coins += (amountInt/5);
amountInt = amountInt % 5;
}
if (1 <= amountInt) {
coins += amountInt;
}
printf ("Coins : %d\n", coins);
}
It seems that no one has answered the particular question
If i try an amount like 9.10 or 9.01, i get a runtime error,signed integer overflow, i understand what it means, but i don't understand how can the value of coins go so high all of a sudden.
so for the sake of completeness, partially as an exercise:
You can find the reason using a debugger. I copied your code and found that it runs for very long. Interrupting it a moment after start revealed that the code freezes repeating this check:
if (fmod(amount, 0.25) == 0) {
amount = amount - 0.25;
coins += 1;
}
At the moment of the interruption amount was about minus 1.2 million and coins almost 5 million. This clearly shows one thing you failed to check: negativity. It can happen easily with floats that you miss the exact zero, as the others have correctly reasoned, no need to repeat that. But if that happens, your program should get worried the moment amount gets negative. Otherwise, under the right conditions, it may as well keep subtracting its way towards negative infinity, and yes, integer overflow will happen in coins.
This is because the computer represent the decimals in binary (power of 2)
For 0.25, the computer can represent it properly in binary. This is because we can obtain 0.25 exactly using power of 2's.
However for 0.10 ( or other denominations mentioned ), they cannot be expressed exactly in powers of 2.
Suppose you try to obtain 0.1 using power of 2's , you won't be able to obtain it exactly. You can just go near it.
0.1 = 0.0625 ( 2^4 ) + 0.03125 ( 2^5 ) + 0.00390625 ( 2^-8) +...
You will approach 0.1 , but you'll never reach 0.1 exactly.
Float, double everyone has a fixed number of bits to represent a decimal. So it will keep only those many bits, whose sum would be slightly less than 0.1
If you want to follow the same approach, you can have 2 possible solutions :-
Use (amount > 0) instead of (amount != 0), or
Use currencies which can be expressed easily in powers of 2 e.g. 0.25, 0.125 , 0.375 , 0.06125.
Your algorithm is not correct:
For example with 30 cents you can exchange to: 25+5 (2 coins) with your algorithm it would be 10+10+10 (3 coins). So greedy means why it's greater than 25 cents then exchange to 25 cents first.
while (amount != 0) {
if (amount >= 0.25) {
amount = amount - 0.25;
coins += 1;
}
else if (amount >= 0.10) {
amount = amount - 0.10;
coins += 1;
}
else if (amount >= 0.05) {
amount = amount - 0.05;
coins += 1;
}
else {
amount = amount - 0.01;
coins += 1;
}
}
If you want to do that way.
Better way:
int coinTypes[] = {0.25, 0.1, 0.05, 0.01};
for (int i = 0; i < 4; i++) {
coins += floor(amount / coinTypes[i];
amount -= coins * coinsTypes[i];
}
The main problem with your algorithm is invalid usage of fmod function. According to definition the result of fmod(num, denom) is
fmod = num - floor(num/denom) * denom
where floor(num/denom) is integer.
Thus, fmod(9.10, 0.25) == 0.1, fmod(9.10, 0.10) == 0.1.
In addition, the manipulation with floating point number rarely gives exact results. so amount is never 0.
You cannot compute this with the float type. Amounts that are not exact multiples of 0.25 cannot be represented exactly in either the float or the double type.
You can fix this problem by computing an exact number of cents and dispatch it using integer arithmetics:
#include <stdio.h>
#include <math.h>
void print_coins(int coins, const char *singular, const char *plural) {
if (coins > 0)
printf(" %d %s", coins, coins > 1 ? plural : singular);
}
int main(void) {
for (;;) {
double amount;
int amountInt, coins, quarters, dimes, nickels, pennies;
printf("Enter amount: ");
if (scanf("%lf", &amount) != 1 || amount <= 0)
break;
amountInt = (int)(amount * 100.0 + 0.5);
quarters = amountInt / 25;
amountInt %= 25;
dimes = amountInt / 10;
amountInt %= 10;
nickels = amountInt / 5;
amountInt %= 5;
pennies = amountInt;
amountInt = 0;
coins = quarters + dimes + nickels + pennies;
printf("coins returned: %d:", coins);
print_coins(quarters, "quarter", "quarters");
print_coins(dimes, "dime", "dimes");
print_coins(nickels, "nickel", "nickels");
print_coins(pennies, "penny", "pennies");
printf("\n");
}
return 0;
}
Notes:
Using float without the + 0.5, the change is incorrect for as little as 100.10: one penny short.
Using float, the change is incorrect for 1000000.10: 3 extra pennies.
To handle amounts above 20 million dollars, you need a larger integral type such as long long int. With that, you can handle amounts exceeding the US national debt.

Error: invalid operands to binary expression ('float' and 'float')

I apologize if this question has been asked before. I looked around and was not able to find a solution, I am new to C.
I understand that I am not able to get a % from a float. How would I be able to capture the remainder of this math, if I am using 2 floats?
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
/*
** Always use the largest coin possible
** keep track of coins used
** Print the final amount of coins
*/
int main (void)
{
float change;
int counter = 0;
int division;
//float rem;
float quarter = 0.25;
//float quarter = 0.25, dime = 0.10, nickel = 0.05, penny = 0.01;
/* Prompt user for an amont of change*/
do{
printf("How much do we owe you in change? ");
change = GetFloat();
}
while (change <= 0);
if (change >= quarter)
{
division = (change / quarter);
counter += division;
//change = (int)(change % quarter);
printf("change: %.2f\n", change);
printf("counter: %d\n ", counter);
}
return (0);
}
You may want to check
fmod.
You can also do something like change = change - (int)(change / quarter) * quarter
You could implement the modulo yourself:
https://en.wikipedia.org/wiki/Modulo_operation
int a = (int)(change / quarter);
int mod = (int)(change - (quarter * a));
Also it might be possible to do it this way:
long mod = ((long)(change * 1000) % (long)(quater * 1000));
depending on the precision of your floats modify the 1000 and think about dividing the result by 1000!
But maybe it would be better to rethink what you really want as result?
Just scale up all your variable by 100 and then use integers instead of float.
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
/*
** Always use the largest coin possible
** keep track of coins used
** Print the final amount of coins
*/
int main (void)
{
float change_f;
int change;
int counter = 0;
int division;
//float rem;
int quarter = 25;
//int quarter = 25, dime = 10, nickel = 5, penny = 1;
/* Prompt user for an amont of change*/
do{
printf("How much do we owe you in change? ");
change_f = GetFloat();
}
while (change_f <= 0);
change = (int)(change_f*100);
if (change >= quarter)
{
division = (change / quarter);
counter += division;
//change = (int)(change % quarter);
printf("change: %.2f\n", change_f);
printf("counter: %d\n ", counter);
}
return (0);
}
NOTE: Choose scale factor according to the input precision i.e if it is 3 decimal digits then choose 1000 and so on.

Resources