将十进制数转换为分数

时间:2012-11-13 16:18:27

标签: c math

我正在尝试将十进制数转换为其分数。十进制数字在小数位后最多有4位数。 例如: - 12.34 = 1234/100 12.3456 = 123456/10000

我的代码: -

#include <stdio.h>
int main(void) {
  double a=12.34;
  int c=10000;
  double b=(a-floor(a))*c;
  int d=(int)floor(a)*c+(int)b; 
  while(1) {
     if(d%10==0) {
    d=d/10;
    c=c/10;
 }
 else break;
  }
  printf("%d/%d",d,c);
 return 0;
}

但我得不到正确的输出,十进制数字只有双精度。请指导我应该做的事。

6 个答案:

答案 0 :(得分:3)

如果您的浮点数为x,那么超过10000的分数的分子将成为(x + 0.00005) * 10000的整数部分。是否要将分数减少到最简单的项(即除以分子和分母的gcd)取决于你。

答案 1 :(得分:2)

#include <stdio.h>

int main(void) {
    double a = 12.34;
    int c = 10000;
    double b = (a - floor(a)) * c;
    int d = (int)floor(a) * c + (int)(b + .5f); 
    printf("%f %d\n", b, d);

    while(1) {
       if(d % 10 == 0) {
           d = d / 10;
           c = c / 10;
       }
       else break;
    }
    printf("%d/%d\n", d, c);
    return 0;
}

问题是b获得了3400.00但是当你(int) b获得3399时,所以你需要添加0.5所以这个数字可以截断为3400。

获得3400.00与3400不同,3400.00意味着该数字是圆形到3400,这就是为什么当你做(int)3400.00时它假设最接近的整数(小于你要转换的数字)是3399,但是,当你向该数字加0.5时,最后一个最接近的整数现在是3400.

如果您想更深入地了解浮点运算,请阅读What Every Computer Scientist Should Know About Floating-Point Arithmetic

答案 2 :(得分:0)

这是一个有趣的问题。 我认为你最好先阅读计算“最大公约数”的倍数方法(http://en.wikipedia.org/wiki/Greatest_common_divisor是一个很好的来源)。

实施快速和肮脏的算法,使用笔和纸进行这些计算,然后查看双精度的表示方式(符号,指数,尾数),并改进算法以利用此表示。

遗憾的是,如果不编写你的代码,我就无能为力。

答案 3 :(得分:0)

使用c ++创建的算法,该算法执行十进制到小数。

#include <iostream>
using namespace std;


// converts the string half of the inputed decimal number into numerical values
void converting (string decimalNumber, float& numerator, float& denominator )

{
float number;
string valueAfterPoint = decimalNumber.substr(decimalNumber.find(".") + 1,((decimalNumber.length() -1) )); // store the value after the decimal into a valueAfterPoint
cout << valueAfterPoint<< " "<< endl;
int length = valueAfterPoint.length(); //stores the length of the value after the decimal point into length

 numerator = atof(valueAfterPoint.c_str()); // converts the string type decimal number into a float value and stores it into the numerator

// loop increases the decimal value of the numerator and the value of denominator by multiples of ten as long as the length is above zero of the decimal

cout << length<< endl;
for (; length > 0; length--)
{
    numerator *= 10;

}
do
    denominator *=10;
    while  (denominator < numerator);

}

// simplifies the the converted values of the numerator and denominator into simpler values for          an easier to read output
  void simplifying (float& numerator, float& denominator)
{
int maximumNumber = 9; //Numbers in the tenths place can only range from zero to nine so the maximum number for a position in a poisitino for the decimal number will be nine

bool isDivisble; // is used as a checker to verify whether the value of the numerator has the       found the dividing number that will a value of zero

// Will check to see if the numerator divided denominator is will equal to zero



if(int(numerator) % int(denominator) == 0)
{
    numerator /= denominator;
    denominator = 1;
    return;
}


//check to see if the maximum number is greater than the denominator to simplify to lowest form
while (maximumNumber < denominator)
{
    maximumNumber *=10;
 }


// the maximum number loops from nine to zero. This conditions stops if the function isDivisible is true
for(; maximumNumber > 0; maximumNumber --)
{

    isDivisble = ((int(numerator) % maximumNumber == 0) && int(denominator)% maximumNumber == 0);
    cout << numerator << denominator <<" " <<endl;
    if(isDivisble)
    {
        numerator /= maximumNumber;  // when is divisible true numerator be devided by the max    number value for example 25/5 = numerator = 5

        denominator /= maximumNumber; //// when is divisible true denominator be devided by the max number value for example 100/5 = denominator = 20

    }
    // stop value if numerator and denominator is lower than 17 than it is at the lowest value
    int stop = numerator + denominator;

    if (stop < 17)
    {
        return;
    }
}
}
  int main()
{
string decimalNumber;
float numerator = 0;
float denominator = 1;

cout << "Enter the decimal number";
cin >> decimalNumber;

//convert function
converting(decimalNumber, numerator, denominator);


//call simplyfication funcition
simplifying(numerator, denominator);


cout<< "Fraction: "<< numerator << "/" << denominator<< endl;
 return 0; 

}

答案 4 :(得分:0)

我的解决方案非常简单,“懒惰”,是迭代运行的,没什么花哨的。

在大多数具有不错的数学库的语言中,您只需要算法本身即可。

但是在公元前,您需要实现简单的功能,例如

int() to return integer part of a number ,
abs() to return absolute value ,
float() to return floating part of a number ,
round() to round to nearest integer.

如果(1 / eps)迭代后未发现任何结果,则循环将中断最后的结果。

eps=10^-4 /*Tweak for more or less accuracy */

define int(x) {
  auto s ;
  s = scale ;
  scale = 0 ;
  x /= 1 ;
  scale = s ;
  return x ;
}
define round(x) { return int(x+.5-(x<0)) ; }
define abs(x) { if ( x < 0 ) x=-x ; return x ; }
define float(x) { return abs(x-int(x)) ; }

define void frac(x) {
    auto f, j, n, z ;
    f = float(x) ;    
    j = 1 / eps ;
    z = .5 ;
    if ( f != 0 ) {
        while ( ( n++ < j ) && ( abs( z - round(z) ) > eps ) ) z = n / f ;
        n -= 1 ;
        if ( x < 0 ) n = -n ;
        x = int(x)
        z = round(z) ;
        print n + x*z , "/" , z , " = "
        if ( x != 0 )  print x , " + " , n , "/" , z , " = "
    }
    print x+n/z , "\n" ;
}

以标准精度(eps = .0001),您可以得到以下内容:

frac(-.714285)
-5/7 = -.71428571428571428571

sqrt(2)
1.414213562373
frac(sqrt(2))
19601/13860 = 1 + 5741/13860 = 1.414213564213

6-7/pi
3.77183080
eps=.000001 ; frac(6-7/pi)
1314434/348487 = 3 + 268973/348487 = 3.77183080

答案 5 :(得分:0)

这是我使用的算法。这是一个迭代过程,其工作方式如下:

  1. 分子的初始近似值为1,分母为1除以浮点值的分数部分。例如,将0.06转换为分数时,分母= 1 / 0.06 = 16.66666667(四舍五入为17),因此初始近似值为1/17。
  2. 计算浮点值和当前近似值之间的差。例如,差异为1/17-0.06 = 0.058824-0.06 = -0.001176。
  3. 如果差异的绝对值小于定义的公差(即0.000005),则迭代终止。
  4. 使用在步骤2中计算出的差值来提高分数的近似值。这是通过将差转换为分数并加(或减)当前近似值来完成的。在此示例中,负差表示较低的近似值-因此需要将差值添加到当前近似值中。分数差为分子= 1和分母= 1 / 0.001176 = 850-分数差为1/850。新的近似值将为(1/17)+(1/850)=(850 * 1 + 17 * 1)/(850 * 17)= 867/14450。
  5. 重复步骤2至4,直到找到解决方案为止。
  6. 找到解决方案后,可以减少分数。例如,867/14450正好是0.06,并且迭代过程终止。 867/14450可以减少到3/50。

此方法的某些功能是:

  • 如果所得分数为1 /任何数值,则第一个近似值将是精确的。例如,将0.25转换为分数,则第一近似值为1/4。因此不需要进一步的迭代。
  • 在1,000,000个测试用例中,绝大多数(> 80%)收敛发生在2次迭代或更短的时间内。
  • 对于所有测试用例,最大迭代次数为3。

我在github上发布了该算法的代码-https://github.com/tnbezue/fraction