Reputation: 51
Trying to create a simple precise calculator using GMP library on C, I came upon a rather unexpected error while testing my program; 2 + 2.22222 = 4.22221999999999999999.
Here is the function I am using from GMP;
mpf_add(res, f1, f2); //with res as result already initilized, f1 and f2 as the values
and as for the printing function;
gmp_printf("%.Ff\n", getExprValue()) //with getExprValue the calculating function that has the line above.
Edit :
Here is the code in its integrity;
int isValidExpression(const char *str) // to check the input
{
int res;
char validOps[6] = {'+', '-', '*', '/', '^', '\0' };
mpf_init(f1);
mpf_init(f2);
// RES = 3 WHEN SYNTAX OK
res = gmp_sscanf(str, "%Ff %c %Ff", f1, &op, f2);
// RES = 4 WHEN OPERAND OK
if(strchr(validOps, op)) res++;
int exprCounter = 0;
char* token = strtok(str, " +-*/^");
while(token != NULL)
{
// TOO MANY WORDS IN THE EXPRESSION
++exprCounter;
if(exprCounter > 2) res = 0;
// TAKE THE NEXT WORD
token = strtok(NULL, " +-*/^");
}
return (res==4);
}
mpf_t* getExprValue() //Working on the operand
{
static mpf_t res;
mpf_init(res);
switch(op)
{
case '+':
mpf_add(res, f1, f2);
break;
case '-':
mpf_sub(res, f1, f2);
break;
case '*':
mpf_mul(res, f1, f2);
break;
case '/':
mpf_sgn(f2) != 0 ? mpf_div(res, f1, f2) : printf("Division by ");
break;
case '^':
mpf_pow_ui(res, f1, mpf_get_si(f2));
break;
}
return res;
}
and as for the main;
char input[MAX_INPUT];
while(gets(input))
{
if(strcmp(input, "exit") != 0)
{
isValidExpression(input) ? gmp_printf("%.Ff\n", getExprValue()) : puts("Expression error");
}
else
{
puts("Exiting...");
break;
}
}
Upvotes: 4
Views: 379
Reputation: 21
The problem is you are trying to decimal arithmetic and using floating point numbers. You need to use a decimal arithmetic library to do exact calculations with decimal numbers.
Upvotes: 2