首先得到小数部分,然后取gcd.使用欧几里德算法http://en.wikipedia.org/wiki/Euclidean_algorithm
void foo(double input)
{
double integral = std::floor(input);
double frac = input - integral;
const long precision = 1000000000; // This is the accuracy.
long gcd_ = gcd(round(frac * precision), precision);
long denominator = precision / gcd_;
long numerator = round(frac * precision) / gcd_;
std::cout << integral << " + ";
std::cout << numerator << " / " << denominator << std::endl;
}
long gcd(long a, long b)
{
if (a == 0)
return b;
else if (b == 0)
return a;
if (a < b)
return gcd(a, b % a);
else
return gcd(b, a % b);
}
Run Code Online (Sandbox Code Playgroud)
#include <iostream>
#include <valarray>
using namespace std;
void as_fraction(double number, int cycles = 10, double precision = 5e-4){
int sign = number > 0 ? 1 : -1;
number = number * sign; //abs(number);
double new_number,whole_part;
double decimal_part = number - (int)number;
int counter = 0;
valarray<double> vec_1{double((int) number), 1}, vec_2{1,0}, temporary;
while(decimal_part > precision & counter < cycles){
new_number = 1 / decimal_part;
whole_part = (int) new_number;
temporary = vec_1;
vec_1 = whole_part * vec_1 + vec_2;
vec_2 = temporary;
decimal_part = new_number - whole_part;
counter += 1;
}
cout<<"x: "<< number <<"\tFraction: " << sign * vec_1[0]<<'/'<< vec_1[1]<<endl;
}
int main()
{
as_fraction(3.142857);
as_fraction(0.1);
as_fraction(0.333333);
as_fraction(514.0/37.0);
as_fraction(1.17171717);
as_fraction(-1.17);
}
x: 3.14286 Fraction: 22/7
x: 0.1 Fraction: 1/10
x: 0.333333 Fraction: 1/3
x: 13.8919 Fraction: 514/37
x: 1.17172 Fraction: 116/99
x: 1.17 Fraction: -117/100
Run Code Online (Sandbox Code Playgroud)
有时您想近似十进制,而不需要等价。例如,pi=3.14159 近似为 22/7 或 355/113。我们可以使用循环参数来获得这些:
as_fraction(3.14159, 1);
as_fraction(3.14159, 2);
as_fraction(3.14159, 3);
x: 3.14159 Fraction: 22/7
x: 3.14159 Fraction: 333/106
x: 3.14159 Fraction: 355/113
Run Code Online (Sandbox Code Playgroud)