这个算法的根本原理是:一个分数对应一条直线的斜率。用数学语言描述就是:一条直线的斜率是无穷大(垂直于X轴)或者是(Y2-Y1) / (X2-X1),我们要做的就是找到2个整数,在指定的精度范围内接近这个斜率。对于正数来说,我们设置分子为0,分母为1,然后比较这个分数同给定的十进制数。如果我们的分数太小了(比如,我们选择的点在直线的下面),我们就加大分子的值直到这个分数太大(比如,这个点在直线的上方),之后我们在增加分母的大小直到这个点在直线下方。如果我们的最终目标是无理数(无限不循环小数),这个算法将一直继续,增加分子和分母,直到最终结果在指定的精度上。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | #include <stdlib.h> #include <iostream.h> #include <math.h> int main() { int iDecimal; int iNumerator, iDenominator, iNegative; double dFraction, dDecimal, dAccuracy, dInteger; cout << "请输入你要转换的数:" ; cin >> dDecimal; iDecimal = ( int )dDecimal; //取整数部分,以在下一步判断输入的是否为整数 if (iDecimal == dDecimal) //判断输入是否为整数,若是则直接输出 { cout << dDecimal << endl; return 0; } if ( abs (iDecimal) >= 1) //如果输入大于等于1,则分解为整数部分和小数部分 { dInteger = iDecimal; dDecimal = dDecimal - iDecimal; } dAccuracy = 0.0001; //设置精度 iNumerator = 0; //初始分子 iDenominator = 1; //初始分母 iNegative = 1; //负数标志 if (iDecimal <0) iNegative = -1; dFraction = 0; while ( fabs (dFraction - dDecimal) > dAccuracy) //判断精度是否达到要求 { if ( fabs (dFraction) > fabs (dDecimal)) iDenominator = iDenominator + 1; //增加分母 else iNumerator = iNumerator + iNegative; //增加分子 dFraction = ( double )iNumerator / ( double )iDenominator; //计算新的分数 } if ( abs (iDecimal) >= 1) cout << dInteger << '+' << '(' << iNumerator << '/' << iDenominator << ')' << endl; else cout << iNumerator << '/' <<iDenominator << endl; return 0; } |