Larger numbers in calculator in C - c

I have written a calculator in C language and everything works well except for when I try to multiply 99999999*99999999 [eight nines by eight nines]. It automatically rounds them to 100 000 000.0 and obviously, I don't want that to happen. I'm using float for numbers and precision up to .1. I tried changing float to double, but it won't work anyway. I have heard something about %g, yet I have found no information about it and I'm not sure how to make it work. Any help is highly appreciated!
EDIT
this is my code:
#include<stdio.h>
#include<math.h>
int main()
{
char op;
float numberone,numbertwo;
printf("Enter the operation: ");
scanf("%f%c%f\n", &numberone, &op, &numbertwo);
switch(op) {
case '+':
printf("%.1f + %.1f = %.1f",numberone, numbertwo, numberone+numbertwo);
break;
case '-':
printf("%.1f - %.1f = %.1f",numberone, numbertwo, numberone-numbertwo);
break;
case '*':
printf("%.1f * %.1f = %.1f",numberone, numbertwo, numberone*numbertwo);
break;
case '/':
if(numbertwo==0){
printf("You cannot divide by zero.");
}
else{
printf("%.1f / %.1f = %.1f",numberone, numbertwo, numberone/numbertwo);}
break;
case'^':
printf("%f ^ %f = %f", numberone, numbertwo, pow(numberone,numbertwo));
break;
default:
printf("Error! operator is not correct");
break;
}
return 0;
}
and when I multiply 99999999*99999999, the result is : 100 000 000.0*100 000 000.0 = 10 000 000 000 000 000.0.

Your program will work with those values, just use double precision, scanf has to use the %lf format specifier in that case. If you want much bigger values you will have to learn libgmp as mentioned in other answers.

#include <stdio.h>
int main(void)
{
float x, y;
scanf("%f %f", &x, &y);
printf("%f\n", x*y);
return 0;
}
,
$ ./c
99999999 99999999
10000000272564224.000000
Do you mean the value is not exact ? This always happens with floating point numbers. 32 bit floats will be precise only up to ~6 decimal digits, while doubles will be ~15 decimal digits.
http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

A floating point number (float, double or long double) store numbers as mantissa and exponent (like 3x10^15, for example, but a bit different and in binary). Therefore you are bound to lose some precision bigger than decimals (= different integer if you convert it back) if you store too big integers.
If you want to handle really big numbers, you can use an arbitrary precision arithmetic library like GMP.

You hit the problem of precision inherent to all standard types. They are represented in a defined number of bits. For the integers (char, short, int, long, long long) when you overflow you pass negative (or 0 for unsigned). Ex for char (8 bits) : 126 + 3 gives ... -127
For the floats (float, double, long double) it may be more subtle, because they are represented as a number of bits for the significand part and some other bits for the exponent part (see more details on Wikipedia. In practice single floats can represent numbers as big as 1038, but with no more than 7 or 8 decimal digits in precision.
If you really want to do exact computations with big numbers, you should use multiple precision technics or directly use the excellent gmp library.

As suggested you could use the libgmp if you need to deal with large numbers. Simplified example based on your code:
#include <stdio.h>
#include <stdlib.h>
#include <gmp.h>
int main(void){
char op;
mpz_t x;
mpz_t y;
mpz_t result;
printf("Enter the operation: ");
scanf("%c\n", &op);
char x_str[256];
char y_str[256];
fgets(x_str, sizeof(x_str), stdin);
fgets(y_str, sizeof(y_str), stdin);
mpz_init(x);
mpz_init(y);
mpz_init(result);
mpz_set_str(x, x_str, 10);
mpz_set_str(y, y_str, 10);
switch(op) {
case '+':
mpz_add(result, x, y);
break;
case '*':
mpz_mul(result, x, y);
break;
default:
printf("Error! operator is not correct");
break;
}
gmp_printf("%Zd", x);
printf(" %c ", op);
gmp_printf("%Zd", y);
gmp_printf(" = %Zd\n", result);
mpz_clear(x);
mpz_clear(y);
mpz_clear(result);
return EXIT_SUCCESS;
}
Compile and linkk with the library:
/tmp$ gcc big.c -lgmp -o big
Then run:
/tmp$ ./big
Enter the operation: *
99999999
99999999
99999999 * 99999999 = 9999999800000001

Related

How to print all the decimal numbers up to the required last digit in C?

I need to print the whole answer in decimal form if the exponent was a negative number. but the float only has 6 decimal places. because if the answer exceeds 6 decimal places the result would only be 0.000000. should I use another data type or what?
#include <stdio.h>
#include <math.h>
float power(int base, int exponent);
int main() {
int base, exponent;
float result;
printf("Enter a base number: "); scanf("%d", &base);
printf("Enter an exponent: "); scanf("%d", &exponent);
result = power(base, exponent);
printf("Power of %d^%d = %f", base, exponent, result);
return 0;
}
float power(int base, int exponent) {
float result = 1;
while (exponent < 0) {
{
result = result / base;
exponent++;
}
}
while (exponent != 0) {
result = result * base;
exponent--;
}
return result;
}
Print specifier
As float is a floating point number (significand and exponent), use "%e" or "%g" to display the number in exponential notation rather than the fixed notation of "%f".
printf("%e\n", result); // exponential
printf("%g\n", result); // exponential for large and tiny values
printf("%a\n", result); // exponential, but with a hexadecimal significand.
To print more than the default of 6 significant decimal digits, use the optional precision:
printf("%.8e\n", result); // 1 + 8 significant decimal places.
As float stores a value internally with a binary significant and OP likely wants a decimal output, it is neither wise to print too few nor informative to print too many significant decimal places. For float, consider using FLT_DECIMAL_DIG (typically 9) to guide the printed decimal precision.
#include <float.h>
printf("%.*e\n", FLT_DECIMAL_DIG-1, result);
// or
printf("%.*g\n", FLT_DECIMAL_DIG, result);
Type
As #pmg suggests, consider double instead of float in C. It is the default floating point type and has 53 binary digits of precision (~17 decimal or so).
Notes
Code like result/base (float/int) and result*base1 can incur a small amount of round-off error on each iterations. With higher exponent, more potentially error.
To "print all the decimal numbers up to the required last digit" can get into some heavy details.
Exponentiation by squaring
Rather than looping, consider Exponentiation by squaring: faster and more accurate.
double pow_f(int ibase, int exponent) {
unsigned expo = exponent < 0 ? 0u - exponent : exponent;
double base = ibase;
double pow = 1.0;
while (expo > 0) {
if (expo % 2) {
pow *= base;
}
base *= base;
expo /= 2;
}
if (ibase < 0) {
pow = 1.0/pow;
}
return pow;
}
Short answer: "%.Nf", where N is the number of digits after point you want.
--- BUT ---
Long answer:
the number of significant (i.e. useful) digits after point depends on the representation of "float" on your machine AND on the magnitude of the value. On most systems the "float" type is IEEE 754 single-precision, wich has 23 bits of mantissa. This roughly corresponds to 7 decimal digits, including the ones BEFORE the decimal point. If the number is big enough, none of the digits after the point is meaningful.
Due to the base-2 representation, most values whose representation in base-10 has a finite number of non-zero digits can't be expressed exactly.

Why does pow(x,y) return inf when x and y are chars?

I understand how to use pow() correctly I'm just wondering why when I run this code ans = inf.
I am having a hard time understanding this.
Does this have anything to do with chars only being able to take on the values -128 to +127 and the way pow() is calculated?
Does this have anything to do with the space in " %c" as in my first scanf param?
Linux 4.9.0-7-amd64
debian 4.9.110-1
gcc version 6.3.020170516
#include <stdio.h>
#include <math.h>
int main ()
{
char base, exp;
float ans;
printf("Enter base number : ");
scanf(" %c", &base);
printf("Enter exp number : ");
scanf(" %c", &exp);
ans = pow(base,exp);
printf("%c raised to the %c power equals %f", base, exp, ans);
return 0;
}
When you enter base and exp using %c you get the characters '0' - '9', not the integer values. So if you enter 0 and 0, the values you get (assuming ASCII encoding) will actually by 48, since that is the ASCII code for '0'. The result of 4848 is roughly 5 x 1080.
You then save the resulting value in a float. Assuming a float is IEEE754 single precision, it can hold an exponent no larger that +/- 38. So you're attempting convert an out-of-range value which invokes undefined behavior, meaning the result is unpredictable. If you changed the type of ans to double you would see the actual result.
Base and exp is not the integer values (0-9). So you want to enter "%d". Not the " %c"

C program to round numbers, rounded to second position after the decimal place [duplicate]

This question already has answers here:
How do I restrict a float value to only two places after the decimal point in C?
(17 answers)
Closed 8 years ago.
I am writing a simple program to round numbers. It works fine when I enter something like 1.4 (gives me 1.0) or 2.6 (gives me 3.0). But when I enter 1.45, it should give me 1.5 but it prints 1.0. Or for 2.85 (should be 2.9, it prints 3.0). How do I make this work? I cannot use any functions.
#include<stdio.h>
const float add = 0.5;
int main(void)
{
float v;
printf("Please enter a value to be rounded: ");
scanf("%f", &v);
v = v + add;
v = (int)v;
printf("The rounded value is %.2f", v);
return 0;
}
Try this code. You need to break your floating value into Modulus and Dividend.
#include<stdio.h>
int main(void)
{
float v;
int con, r_value, mul;
printf("Please enter a value to be rounded: ");
scanf("%f", &v);
mul=v*10;
con=mul%10;
r_value=mul/10;
if(con>=5)
r_value=r_value+1;
else
r_value=r_value;
printf("The rounded value is %.2d", r_value);
return 0;
}
Above code is modified to be used for Negative Numbers also.
float v;
int con, r_value, mul;
printf("Please enter a value to be rounded: ");
scanf("%f", &v);
mul=v*10;
con=mul%10;
r_value=mul/10;
if(v>0)
{
if(con>=5)
r_value=r_value+1;
else
r_value=r_value;
}
else if (v<0)
{
if(con<=-5)
r_value=r_value-1;
else
r_value=r_value;
}
printf("The rounded value is %.2d", r_value);
Int value simply removes the value after decimal point it does't round of to nearest number
In your case when you give 2.45
2.45 + 0.5 = 2.95
which is rounded off to 2(2.0 since your asking for precision) i.e the decimal part is truncated not rounded off.
Ints do not have decimal places, so a cast from float to int then back to float will leave only the integer value.
Your subject (rounding to the second decimal place) does not match your question (rounding to an arbitrary position based on the input). That makes it difficult to answer your question properly.
That said, your code
v = v + 0.5;
v = (int)v;
will round a number to the nearest integer. I'm not sure why you expect the int cast to do anything else.
You are using v = (int)v;, how can it give 1.5 for input of 1.45.
To get what you want, you can just print the decimal digits 1 less than in original, i.e.
Suppose you have 2.455 which has 3 decimal digits, you can just print that number using %.2f and it will automatically be rounded off.
You can do:
printf("%.2f", ((int)(v * 100 + 0.5) / 100.0));

How to get the integer and fractional part of a decimal number as two integers in Arduino or C?

How do I convert 30.8365146 into two integers, 30 and 8365146, for example, in Arduino or C?
This problem faces me when I try to send GPS data via XBee series 1 which don't allow to transmit fraction numbers, so I decided to split the data into two parts. How can I do this?
I have tried something like this:
double num=30.233;
int a,b;
a = floor(num);
b = (num-a) * pow(10,3);
The output is 30 and 232! The output is not 30 and 233. Why and how can I fix it?
double value = 30.8365146;
int left_part, right_part;
char buffer[50];
sprintf(buffer, "%lf", value);
sscanf(buffer, "%d.%d", &left_part, &right_part);
and you will get left/right parts separately stored in integers.
P.S. the other solution is to just multiply your number by some power of 10 and send as an integer.
You can output the integer to a char array using sprintf, then replace the '.' with a space and read back two integers using sscanf.
I did it for float, using double as temporary:
int fract(float raw) {
static int digits = std::numeric_limits<double>::digits10 - std::numeric_limits<float>::digits10 - 1;
float intpart;
double fract = static_cast<double>(modf(raw, &intpart));
fract = fract*pow(10, digits - 1);
return floor(fract);
}
I imagine that you could use quadruple-precision floating-point format to achieve the same for double: libquadmath.
The 30 can just be extracted by rounding down (floor(x) in math.h).
The numbers behind the decimal point are a bit more tricky, since the number is most likely stored as a binary number internally, this might not translate nicely into the number you're looking for, especially if floating point-math is involved. You're best bet would probably be to convert the number to a string, and then extract the data from that string.
As in the comments, you need to keep track of the decimal places. You can't do a direct conversion to integer. A bit of code that would do something like this:
#include <stdio.h>
#include <math.h>
#define PLACES 3
void extract(double x)
{
char buf[PLACES+10];
int a, b;
sprintf(buf, "%.*f", PLACES, x);
sscanf(buf, "%d.%d", &a, &b);
int n = (int) pow(10, PLACES);
printf("Number : %.*f\n", PLACES, x);
printf(" Integer : %d\n", a);
printf(" Fractional part: %d over %d\n", b, n);
}
int main()
{
extract(1.1128);
extract(20.0);
extract(300.000512);
}
Produces:
Number : 1.113
Integer : 1
Fractional part: 113 over 1000
Number : 20.000
Integer : 20
Fractional part: 0 over 1000
Number : 300.001
Integer : 300
Fractional part: 1 over 1000
What about using floor() to get the integer value and
num % 1 (modulo arithmetic) to get the decimal component?
Then you could multiply the decimal component by a multiple of 10 and round.
This would also give you control over how many decimal places you send, if that is limited in your comm. standard.
Would that work?
#include <math.h>
integer_part = floor(num);
decimal_part = fmod(num,1)*10^whatever;

How Can I Convert Float to Int with Modulus in C?

I am so confused with Modulus in C. I am writing a small script that allows the user to input their two number vars, then they can either add, subtract, multiply, divide (easy) or modulus (haven't caught this one yet). What would I be doing wrong in this? I get the "invalid operands to binary %" error, which means I need to format it to an int since it is a float. However what is the best way of doing this with the following? Any C help would be greatly appreciated.
int main (void)
{
float number1, number2, result;
char symbol;
//allow user interaction
printf("Enter your formula: \n");
scanf("%f %c %f", &number1, &symbol, &number2);
switch (symbol) {
case '%':
result = number1 % number2;
printf("Result: %f \n", result);
break;
default:
printf("Operation Error. Program aborted. \n \n");
break;
}
printf("Press any key to continue \n");
getchar();
return 0;
}
Where and how do I convert this?
You can either use a statement like:
result = (int)number1 % (int)number2;
to cast your floats to ints and perform the modulus operation, but you'll lose the decimal precision.
You could also include math.h and use fmod
result = fmod(number1, number2);
I recommend to use the fmod function of the standard C library.
The % operator only works on integer types. To perform the same task with floating points, you'd want to do something like:
#include <math.h>
float modulus(float a, float b)
{
return a - b * floor(a / b);
}
Mod is an integer operation, so it cannot be used on floats. Your case should read something like:
result = (int)number1 % (int)number2;
which will convert both floats to integers, and perform the mod. However, note that you are losing precision by casting a floating point number to an integer, so it is likely the result may not be what you'd expect.
change
case '%':
result = number1 % number2;
to
case '%':
result = (int)number1 % (int)number2;
?
modulo division is for integers. Cast each operand to an integer.

Resources