So I am trying to write a program which takes a floating point value and represents it in terms of a fraction. I am facing a weird problem. This is my program:
#include<stdio.h>
#include<math.h>
int gcd(int,int);
void main()
{
int n,n1,n2,g;
float a,a1;
printf("Enter number of digits after decimal point: ");
scanf("%d",&n);
printf("Enter number: ");
scanf("%f",&a);
n2=pow(10,n);
a1=a*n2;
n1=(int)a1;
g=gcd(n1,n2);
n1/=g;n2/=g;
printf("The number is %d/%d",n1,n2);
}
int gcd(int a,int b)
{
int x,flag=0;
int n1=((a>b)?a:b);
int n2=((a<b)?a:b);
for(x=n1;x>=1;x--)
{
if(n1%x==0 && n2%x==0)
{
flag=1;break;
}
}
if(flag==1)
return x;
else
return 1;
}
Now this program gives the correct answer for numbers with only 1 decimal point. For example:
Enter number of digits after decimal point: 1
Enter number: 2.5
The number is 5/2
However for number with two or more digits after decimal point it gives a wrong answer. For example:
Enter number of digits after decimal point: 2
Enter number: 2.50
The number is 247/99
I know that floating point numbers are not accurate but I did not expect this big a variation. Is there any way to work around this and make this program work???
Works for me. I believe the reason is that you use pow(10, n) and pow is inexact on your platform. Use a simple for-loop instead:
n2 = 1;
for (int c = 0; c < n; c++) {
n2 *= 10;
}
As functions like pow(10, n) may generate results near an integer value instead of an exact integer value. Rather than truncating with (int), use one of the round functions should you want to continue using pow().
Consider long int lround(double x), long int lroundf(float x) which round and covert to an integer type in one call.
The lround and llround functions round their argument to the nearest integer value, rounding halfway cases away from zero, regardless of the current rounding direction. C11 §7.12.9.7 2
n2 = lround(pow(10,n));
a1 = a*n2;
n1 = lroundf(a1);
Related
I'm trying to build a calculator, which input a number n it can automatically output the sum of
1/2+2/2 +1/3+2/3+3/3 +...+1/n+2/n+...+n/n and for each denominator, print the result once.
The calculator will restart and ask for input after output the final result of 1/2+2/2 +1/3+2/3+3/3 +...+1/n+2/n+...+n/n .And when the the user decides to stop the program enter 0.
for input=3 ,the output is sum =1 ,sum=2 ,yet I expected it to be sum=3/2, sum=7/2
Here's the program
#include <stdio.h>
int main(){
printf("Please enter the max denominator:\n");
int i,j,n;
int sum=0;
do{
scanf("%d",&n);
for (j=2;j<=n;j++){
for(i=1;i<=j;i++){
sum+= i/j;
if (i==j){
printf("sum=%d\n",sum);
break;
}
}
}
} while (n!=0);
return 0;
}
EDIT: revised part due to advice
int i,j,n;
double sum=0.0;
do{
scanf("%d",&n);
sum=0.0;
for (j=2;j<=n;j++){
for(i=1;i<=j;i++)
sum+=(double)i/j;
printf("sum=%lf\n",sum);
}
} while (n!=0);
return 0;
}
Your program is working with integers. i, j, n, and sum are all integers. This means they cannot encode numbers like 3/2 or 7/2.
So what happens when you divide two integers, like 1/2? The answer is that the result rounds down to the nearest integer. Since 1/2 is 0.5, the nearest integer below that is 0, so the result is 0.
You need to use float, which uses floating point arithmetic. Floating point arithmetic has its own set of fun rounding issues (You may be surprised to find that "0.2" cannot be represented exactly with floating point numbers).
A more exact alternative is to write your own functions to handle rational numbers as a pair of integers -- a numerator and a denominator. It will require additional algorithms (such as a Greatest Common Divisor algorithm), but it can describe these sorts of problems exactly.
I am trying to reverse a two digit number, and I understand there may be better ways of doing this, but I am curious now why the way I chose does not work.
If I input 48, it produces 84 (a successful reversal).
If I input 84, it produces 38. If I input 47, it produces 64. These are just some examples of unsuccessful reversals.
int digit_one, digit_two, input;
float a, b;
printf("Enter a two-digit number: ");
scanf("%d", &input);
a = input * 0.1; // turns the two digit input figure into a float with a digit after the decimal point
digit_one = a; // turns the float into an integer, eliminating the digit after the decimal point
b = a - digit_one; // produces a float that has a 0 before the decimal point, and a digit after the decimal point
digit_two = b * 10; // moves the digit that was after the decimal point, to before the decimal point
printf("The reversal is: %d%d\n", digit_two, digit_one);
Thank you!
a - digit_one is a fractional number. If it's slightly less than the exact result (because for example 0.7 cannot be represented exactly as a float), then (a - digit_one) * 10 will be slightly less than the desired integer, and so digit_two will be one less than you expect.
You can avoid floating point, and write int digit_one, digit_two = input / 10, input % 10;
Working with floats is not the best approach here. With the input "84", b * 10 = 3.999996 which is 3 when you convert it to an integer.
This is a classic computer science problem with floats. Here are some links where this has been explained very well:
Is floating point math broken?
https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Your problem can be solved differently:
int digit_one, digit_two, input, a, b;
printf("Enter a two-digit number: ");
scanf("%d", &input);
digit_one = input % 10;
digit_two = (input / 10) % 10;
printf("The reversal is: %d%d\n", digit_one, digit_two);
int result =0;
do{
result = (result * 10) + (input % 10);
input /= 10;
} while(input)
printf("The reversal is: %d\n", result);
You can print the 'result' variable to get any integer value irrespective of 2 digit or 3 digit
I've made a program in C that takes two inputs, x and n, and raises x to the power of n. 10^10 doesn't work, what happened?
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
float isEven(int n)
{
return n % 2 == 0;
}
float isOdd(int n)
{
return !isEven(n);
}
float power(int x, int n)
{
// base case
if (n == 0)
{
return 1;
}
// recursive case: n is negative
else if (n < 0)
{
return (1 / power(x, -n));
}
// recursive case: n is odd
else if (isOdd(n))
{
return x * power(x, n-1);
}
// recursive case: n is positive and even
else if (isEven(n))
{
int y = power(x, n/2);
return y * y;
}
return true;
}
int displayPower(int x, int n)
{
printf("%d to the %d is %f", x, n, power(x, n));
return true;
}
int main(void)
{
int x = 0;
printf("What will be the base number?");
scanf("%d", &x);
int n = 0;
printf("What will be the exponent?");
scanf("%d", &n);
displayPower(x, n);
}
For example, here is a pair of inputs that works:
./exponentRecursion
What will be the base number?10
What will be the exponent?9
10 to the 9 is 1000000000.000000
But this is what I get for 10^10:
./exponentRecursion
What will be the base number?10
What will be the exponent?10
10 to the 10 is 1410065408.000000
Why does this write such a weird number?
BTW, 10^11 returns 14100654080.000000, exactly ten times the above.
Perhaps it may be that there is some "Limit" to the data type that I am using? I am not sure.
Your variable x is an int type. The most common internal representation of that is 32 bits. That a signed binary number, so only 31 bits are available for representing a magnitude, with the usual maximum positive int value being 2^31 - 1 = 2,147,483,647. Anything larger that that will overflow, giving a smaller magnitude and possibly a negative sign.
For a greater range, you can change the type of x to long long (usually 64 bits--about 18 digits) or double (usually 64 bits, with 51 bits of precision for about 15 digits).
(Warning: Many implementations use the same representation for int and long, so using long might not be an improvement.)
A float only has enough precision for about 7 decimal digits. Any number with more digits than that will only be an approximations.
If you switch to double you'll get about 16 digits of precision.
When you start handling large numbers with the basic data types in C, you can run into trouble.
Integral types have a limited range of values (such as 4x109 for a 32-bit unsigned integer). Floating point type haver a much larger range (though not infinite) but limited precision. For example, IEEE754 double precision can give you about 16 decimal digits of precision in the range +/-10308
To recover both of these aspects, you'll need to use a bignum library of some sort, such as MPIR.
If you are mixing different data types in a C program, there are several implicit casts done by the compiler. As there are strong rules how the compiler works one can exactly figure out, what happens to your program and why.
As I do not know all of this casting rules, I did the following: Estimating the maximum of precision needed for the biggest result. Then casting explicit every variable and funktion in the process to this precision, even if it is not necessary. Normally this will work like a workarount.
I'm trying to print out the decimal expansion of a rational number in C. The problem I have is that when I divide the numerator by the denominator I lose precision. C rounds up the repeating part when I don't want it to.
For example, 1562/4995 = 0.3127127127... but in my program I get 1562/4995 = 0.312713. As you can see a part of the number that I need has been lost.
Is there a way to specify C to preserve a higher level of decimal precision?
I have tried to declare the result as a double, long double and float. I also tried to split the expansion into 2 integers seperated by a '.'
However both methods haven't been successful.
int main() {
int numerator, denominator;
numerator = 1562;
denominator = 4995;
double result;
result = (double) numerator / (double) denominator;
printf("%f\n", result);
return 0;
}
I expected the output to be 1562/4995 = 0.3127127127... but the actual output is 1562/4995 = 0.312713
The %f format specifier to printf shows 6 digits after the decimal point by default. If you want to show more digits, use a precision specifier:
printf("%.10f\n", result);
Also, the double type can only accurately store roughly 16 decimal digits of precision.
You need to change your output format, like this:
printf("%.10lf\n", result);
Note two things:
The value after the . specifies the decimal precision required (10 decimal places, here).
Note that I have added an l before the f to explicitly state that the argument is a double rather than a (single-precision) float.
EDIT: Note that, for the printf function, it is not strictly necessary to include the l modifier. However, when you come to use the 'corresponding' scanf function for input, it's absence will generate a warning and (probably) undefined behaviour:
scanf("%f", &result); // Not correct
scanf("%lf", &result); // Correct
If printing is all you want to do, you can do this with the same long division you were taught in elementary school:
#include <stdio.h>
/* Print the decimal representation of N/D with up to
P digits after the decimal point.
*/
#define P 60
static void PrintDecimal(unsigned N, unsigned D)
{
// Print the integer portion.
printf("%u.", N/D);
// Take the remainder.
N %= D;
for (int i = 0; i < P && N; ++i)
{
// Move to next digit position and print next digit.
N *= 10;
printf("%u", N/D);
// Take the remainder.
N %= D;
}
}
int main(void)
{
PrintDecimal(1562, 4995);
putchar('\n');
}
This is a program to find number of digits.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main() {
int i = 0, n;
printf("Enter number: ");
scanf("%d", &n);
while ((n / pow(10, i)) != 0) {
i++;
}
printf("%d", i);
}
This program gives 309 as the output (value of i) on any input. However, if I store the value of pow(10, i) in another variable and put it in while loop, I get the correct output. Please help!
C++ uses the most precise type (when types are mixed) when doing a calculation or evaluation, and here you are effectively mixing a double with an int. You are dividing a user input number by a very large exponential number.
This in theory will never be zero, no matter how big the divisor gets. So, the theoretical result should be infinite. However, due to the limits of a double (which is returned by pow), it will still eventually approximate zero.
If you store the return of pow in an integer, you will no longer be mixing types and will effectively be working out the number of digits or what the approximate log base 10 is (any integer divide by a larger integer will equal zero).
Change:
while( ( n / pow(10,i) )!=0 ){
To:
while( ( n / pow(10,i) ) >= 1 ){
pow returns double and therefore the full result is double and the fractional part will be always non-zero until running out of exponent possible values which is 309 (translated to decimal, binary is 1024).