2017-05-06 87 views
2

所以我试图编写一个程序,它采用浮点值并以分数表示。我正面临一个奇怪的问题。这是我的程序:程序将打印浮点值转换为分数不工作..?

#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; 

} 

现在这个程序给出了只有一个小数点的数字的正确答案。例如:

Enter number of digits after decimal point: 1 
Enter number: 2.5 
The number is 5/2 

但是,对于小数点后有两位或更多位的数字,它会给出错误的答案。例如:

Enter number of digits after decimal point: 2 
Enter number: 2.50 
The number is 247/99 

我知道浮点数不准确,但我没有想到这个大的变化。有没有什么办法可以解决这个问题,并使这个程序工作?

+3

浮点数是不是* *总是准确的,但2.5 *为*准确;因此你的算法被破坏了。 –

+1

'pow'替换为int pows(int x,int n){ \t int p = 1; (n--) \t while(n--) \t \t p * = x; \t return p; }' – BLUEPIXY

+1

还有:'int main(void)' –

回答

5

适合我。我相信原因是你使用pow(10, n)powinexact on your platform。用一个简单的for循环,而不是:

n2 = 1; 
for (int c = 0; c < n; c++) { 
    n2 *= 10; 
} 
+0

Thanks .. that工作!感觉有点愚蠢,我不知道这.... –

+0

@Antti Haapala我不知道'n1 =(int)a1;'也可能会给出错误的值,因为a1可能被存储为249.999 ...,导致n1是249. –

+3

@ X.Liu:很容易放弃浮点数并将其作为字符串读取。然后对小数点后面的数字进行计数(不要让用户告诉你),并去掉小数点并将其转换为适当的大整数,然后对GCD执行10^n,其中n是小数点后的位数点。这可以避免所有浮点不准确问题。 –

0

作为像pow(10, n)功能可以产生近的整数值,而不是一个确切的整数值的结果。如果您想继续使用pow(),请使用其中一个轮功能,而不是使用(int)截断。

考虑long int lround(double x),long int lroundf(float x)在一次调用中轮换并转换为整数类型。

lround的和llround功能圆他们的说法为最接近的整数值,舍入半例远离零,而不考虑当前的舍入方向的。 C11§7.12.9.72

n2 = lround(pow(10,n)); 
a1 = a*n2; 
n1 = lroundf(a1);