簡體   English   中英

將十進制數轉換為分數

[英]Convert Decimal number into Fraction

我正在嘗試將十進制數轉換為其分數。 小數位后的小數位數最多為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;
}

但是我沒有得到正確的輸出,十進制數只能是雙精度。請指導我該怎么做。

如果您的浮點數為x ,則分數超過10000的分子將是(x + 0.00005) * 10000的整數部分。 由您決定是否要將分數減少為最簡單的項(即除以分子和分母的gcd)。

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

如果您想更深入地了解浮點算法,請閱讀每位計算機科學家應該了解的有關浮點算法的知識。

這是個有趣的問題。 我認為從閱讀“最大公因數”的倍數計算方法開始可能會更好( http://en.wikipedia.org/wiki/Greatest_common_divisor是一個很好的來源)。

實現一種快速臟算法,就像使用筆和紙一樣進行那些計算,然后研究如何表示雙精度(符號,指數,尾數),並改進算法以利用這種表示。

不幸的是,如果不編寫您的代碼,我將無能為力。

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

}

我的解決方案非常簡單,“懶惰”,是通過迭代運行的,沒什么花哨的。

在大多數具有不錯的數學庫的語言中,您只需要算法本身即可。

但是在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

這是我使用的算法。 這是一個迭代過程,其工作方式如下:

  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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM