2

我正在尝试将十进制数转换为其分数。小数点后最多有 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;
}

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

4

6 回答 6

4

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

于 2012-11-13T16:26:27.707 回答
1
#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。

如果您想更深入地了解浮点运算,请阅读每个计算机科学家应该了解的关于浮点运算的知识

于 2012-11-13T16:51:36.163 回答
1

我的解决方案很简单,“懒惰”,通过迭代运行,没什么花哨的。

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

但是在 bc 中,您需要实现简单的功能,例如

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
于 2019-08-15T22:56:27.027 回答
1

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

  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/anything,则第一个近似值将是精确的。例如,将 0.25 转换为分数,第一个近似值将是 1/4。因此不需要进一步的迭代。
  • 在 1,000,000 个测试用例中的大多数(> 80%)中,收敛发生在 2 次或更少的迭代中。
  • 对于所有测试用例,最大迭代次数为 3。

我在 github 上发布了这个算法的代码——https: //github.com/tnbezue/fraction

于 2019-09-17T03:48:21.777 回答
0

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

实现一个快速而肮脏的算法,像用笔和纸一样进行这些计算,然后研究双精度数的表示方式(符号、指数、尾数)并改进您的算法以利用这种表示。

可悲的是,如果不编写您的代码,我将无能为力。

于 2012-11-13T16:30:01.393 回答
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; 

}
于 2014-10-29T06:00:07.127 回答