将浮点十进制转换为分数

7

给定一个十进制浮点数值,如何找到它的分数等价或近似值?例如:

as_fraction(0.1) -> 1/10
as_fraction(0.333333) -> 1/3
as_fraction(514.0/37.0) -> 514/37

有通用的算法可以将十进制数转换为分数形式吗?在C ++中如何简单高效地实现这个算法?


一个想法,只是一个想法,找到一种方法来找到2个分数,一个比答案小,另一个比答案大。然后从那里开始循环,朝着彼此靠近并找到最接近的,除非总会有一个整数。 - Evan Carslake
“十进制”是指您的输入是一个十进制数字和一个小数点的字符串,还是仅仅表示不是整数?请注意,十进制和二进制浮点数实际上都是分数的表示形式,但不一定是您想到的那个分数。例如,无论是二进制还是十进制中1/3的表示形式实际上都是不同的数字。 - Ben Voigt
这个答案中概述了一个高效的算法:https://dev59.com/sWfWa4cB1Zd3GeqPi58C#12101996 它找到逐渐接近“好”的形式的分数近似值。 - Michael Anderson
2
我写了一个答案,但由于此问题已关闭,我把它放在了 gist 上:https://gist.github.com/mikeando/7073d62385a34a61a6f7 - Michael Anderson
1
在https://dev59.com/T2435IYBdhLWcg3w7k6b#5128558上有一个稍微更好的答案,而我的gist现在包含了一个C++实现以及两种方法的比较。 - Michael Anderson
虽然这是一个老问题,但使用连分数可以得到一系列越来越好的近似值。例如,pi≈3; pi≈3+1/7; pi≈3+1/(7+1/16)=3+16/113; pi≈3+1/(7+1/(16-1/294))=3+4703/33215 -> 精确到10位数字! - Sebastian
6个回答

11

首先获取小数部分,然后取gcd。使用欧几里得算法http://zh.wikipedia.org/wiki/欧几里得算法

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);
}

我认为你不应该除以分母,这样做也不会找到“最好”的分数,但这是一种合理的方法来得到一些约分后的分数。 - Ben Voigt
1
这个网站可以帮助一些人理解你的算法:http://www.webmath.com/dec2fract.html - Ludovic Feltz
@Ludovic:那个网页使用了非常不同的算法。尝试在其中输入“0.3333333”。 - Ben Voigt
@benVoigt,好的,我明白你的意思了,但这可以帮助我们更好地理解,不是吗? - Ludovic Feltz
1
糟糕,那个 web2frac 真是太糟糕了。我在 1.17171 上尝试了一下,没有得到任何有价值的东西。我在我的代码片段中使用的算法依次给出了更好的近似值 "41/35"、"116/99" 和 "1549/1322"。 - Michael Anderson
显示剩余4条评论

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

有时候,您希望近似表示小数而不需要等价的值。例如,pi=3.14159 可以近似表示为 22/7 或 355/113。我们可以使用 cycles 参数来获取这些值:

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

@dxiv 增加循环次数和精度,你就会得到结果。例如 as_fraction(0.33328,10, 1e-7); - Onyambu
1
@Onyambu 谢谢,但那只会转移问题到不同的例子。您能否在答案中说明一下cyclesprecision通常预期的结果是什么?如果没有这个,我甚至无法确定 1/3 在这些情况下是否是正确的答案,因为我不知道该函数应该返回什么。 - dxiv
1
@Onyambu,你在自己的机器上得到与我链接中的1/3不同的结果只能证明这是实现相关的,并且本质上是不可靠的。暂且不论这一点,你仍然没有定义函数在其参数方面应该返回什么。我不明白一个行为未指定的函数的意义所在。类似"as_fraction 返回<任何东西>"的描述才是适当的。"如果你不喜欢结果,请使用不同的 precision"则不是。 - dxiv
@dxiv 从技术上讲,1/3没有十进制等价数,但我们仍将0.3333作为近似值。 - Onyambu
定义as_fraction函数的主要困难在于,只要在循环中使用浮点数计算,就无法保证一致的结果。我的其他评论必须以某种方式成为“答案”,因为它们无法适应此处。 - dxiv
显示剩余5条评论

1
(评论太长了。)

一些评论声称这是不可能的。但我持相反意见。

我认为在正确的解释下是可能的,但很容易错误地陈述问题或误解答案。

这里提出的问题是找到给定浮点数值的有理近似值。

这当然是可能的,因为C++中使用的浮点格式只能存储有理数值,通常采用符号/尾数/指数形式。以IEEE-754单精度格式为例(为了使数字更简单),0.333存储为1499698695241728 * 2^(-52)。这相当于分数1499698695241728 / 2^52,其收敛数提供越来越准确的近似值,一直到原始值:1/3333/100077590/2330035586813/16777216

这里需要注意两点。

  • 对于变量float x = 0.333;,最佳有理逼近值不一定是333 / 1000,因为存储的值并不是精确的0.333,而是由于浮点数内部表示的有限精度,实际存储的值为0.333000004291534423828125

  • 一旦赋值,浮点数值就不会记得它来自哪里,或者源代码是否将其定义为float x = 0.333;float x = 0.333000004;,因为这两个值具有相同的内部表示。这就是为什么(相关但不同的)将数字的字符串表示(例如用户输入的值)分离为整数和小数部分的问题不能通过首先转换为浮点数然后在转换后的值上运行浮点数计算来解决。


[ 编辑 ] 以下是 0.333f 示例的详细步骤。

  1. float 转换为精确分数的代码。
#include <cfloat>
#include <cmath>
#include <limits>
#include <iostream>
#include <iomanip>

void flo2frac(float val, unsigned long long* num, unsigned long long* den, int* pwr)
{
    float mul = std::powf(FLT_RADIX, FLT_MANT_DIG);
    *den = (unsigned long long)mul;
    *num = (unsigned long long)(std::frexp(val, pwr) * mul);
    pwr -= FLT_MANT_DIG;
}

void cout_flo2frac(float val)
{
    unsigned long long num, den; int pwr;
    flo2frac(val, &num, &den, &pwr);

    std::cout.precision(std::numeric_limits<float>::max_digits10);
    std::cout << val << " = " << num << " / " << den << " * " << FLT_RADIX << "^(" << pwr << ")" << std::endl;
}

int main()
{
    cout_flo2frac(0.333f);
}
  1. 输出
0.333000004 = 11173626 / 16777216 * 2^(-1)
  1. 这将float val = 0.333f;的有理表示形式设置为5586813/16777216

  2. 剩下要做的是确定精确分数的连分数收敛值,这可以只使用整数计算完成。 end result(由WA提供)。

0, 1/3, 333/1000, 77590/233003, 5586813/16777216

你可以尝试一下as_fractions(0.333),它会给你333/1000而不是1/3,但如果你尝试增加小数位数,比如as_fractions(0.333333333),这将给你1/3。那么你想要表达什么意思?有什么争议吗?获取任何简单的分数,即最多4个有效数字,并尝试一下,看看是否能得到你想要的结果。这里的概念是尝试做一个近似值。首先,我们无法精确地表示1/3。即使是一个简单的0.1,在二进制中也没有精确的表示方法。我提供的方法是一个简单的连分数... - Onyambu
被Matlab和R以及可能其他编程语言使用,用于表示小数的分数等价形式。在Matlab中,精度为1e-6,其中0.3333333将变为1/3,因此0.33333333768仍将是1/3。所以我只是提供了一个在C++中解决问题的快速方法。您可以编写相同的函数,同时让默认精度为1e-8,这样您就可以获得相当准确的分数近似值。 - Onyambu
如果我想要某个特定的结果,我一开始就不需要调用该函数;-) 对于“简单的例子”,as_fraction(987.0/610.0); 返回 144/89(4181.0/6765.0) 返回 55/89。我并不是说这些结果是错误的,也不能说它们是正确的,因为该函数没有设定任何期望返回的内容。@Onyambu "获取任何小数,即最多4位有效数字,并尝试一下,看看您是否无法获得所需的结果"。 - dxiv
我感觉我们处于不同的频谱。你能否定义一个函数,将十进制数转换为其近似/等价分数,就像在Matlab、R、Python和其他语言中一样,并在此处发布它。让它不要太复杂。我确实会接受你的答案。 - Onyambu
是的,确实没有一个精确等于0.1的双精度数。这是事实。但是你能得到0.1的有理逼近吗?请注意,这个有理逼近在Mathematica、Matlab、Python、R等软件中都被使用。那么争议在哪里呢?我的函数是一个简单的函数,可以进行有理逼近。它是否100%正确?当然不是。即使是Matlab中内置的函数也不是100%准确的。 - Onyambu
显示剩余5条评论

0
#include<iostream>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<string>
#include<vector>
#include <exception>
#include <sstream>

// note using std = c++11
// header section

#ifndef rational_H
#define rational_H

struct invalid : std::exception {
    const char* what() const noexcept { return "not a number\n"; }};

struct Fraction {
public:
    long long value{0};
    long long numerator{0};
    long long denominator{0};
}; Fraction F;

class fraction : public Fraction{

public:
    fraction() {}
    void ctf(double &);
    void get_fraction(std::string& w, std::string& d, long double& n) {
        F.value = (long long )n;
        set_whole_part(w);
        set_fraction_part(d);
        make_fraction();
    }
    long long set_whole_part(std::string& w) {
        return whole = std::stoll(w);
    }
    long long set_fraction_part(std::string& d) {
         return decimal = std::stoll(d);
    }
    void make_fraction();
    bool cmpf(long long&, long long&, const long double& epsilon);
    int Euclids_method(long long&, long long&);

    long long get_f_part() { return decimal; };
    void convert(std::vector<long long>&);
    bool  is_negative{ false };

    friend std::ostream& operator<<(std::ostream& os, fraction& ff);
    struct get_sub_length;

private:
    long long whole{ 0 };
    long long decimal{ 0 };
};
#endif // rational_H

// definitions/source

struct get_sub_length {
    size_t sub_len{};
    size_t set_decimal_length(size_t& n) {
        sub_len = n;
        return sub_len;
    }
    size_t get_decimal_length() { return sub_len; }
}; get_sub_length slen;

struct coefficient {
    std::vector<long long>coef;
}; coefficient C;

//compare's the value returned by convert with the original 
// decimal value entered.
//if its within the tolarence of the epsilon consider it the best
//approximation you can get.
//feel free to experiment with the epsilon.
//for better results.
 
bool fraction::cmpf(long long& n1, long long& d1, const long double& epsilon = 0.0000005) 
{
long double ex = pow(10, slen.get_decimal_length());
long long  d = get_f_part();       // the original fractional part to use for comparison.
long double  a = (long double)d / ex;
long double b = ((long double)d1 / (long double)n1);
if ((fabs(a - b) <= epsilon)) { return true; }
return false;
}

//Euclids algorithm returns the cofficients of a continued fraction through recursive division,
//for example: 0.375 -> 1/(375/1000) (note: for the fractional portion only).
// 1000/375 -> Remainder of 2.6666.... and  1000 -(2*375)=250,using only the integer value
// 375/250 -> Remainder of 1.5  and   375-(1*250)=125,
// 250/125 -> Remainder of 2.0  and   250-(2*125)=2
//the coefficients of the continued fraction are the integer values 2,1,2
// These are generally written [0;2,1,2] or [0;2,1,1,1] were 0 is the whole number value.

int fraction::Euclids_method(long long& n_dec, long long& exp) 
{

    long long quotient = 0;

    if ((exp >= 1) && (n_dec != 0)) {
        quotient = exp / n_dec;

        C.coef.push_back(quotient);

        long long divisor = n_dec;
        long long dividend = exp - (quotient * n_dec);

        Euclids_method(dividend, divisor); // recursive division 
    }
    return 0;
}

 // Convert is adding the elements stored in coef as a simple continued fraction
// which should result in a good approximation of the original decimal number.

void fraction::convert(std::vector<long long>& coef) 
{
    std::vector<long long>::iterator pos;
    pos = C.coef.begin(), C.coef.end();
    long long n1 = 0;
    long long n2 = 1;
    long long d1 = 1;
    long long d2 = 0;

    for_each(C.coef.begin(), C.coef.end(), [&](size_t pos) {

        if (cmpf(n1, d1) == false) {

            F.numerator = (n1 * pos) + n2;
            n2 = n1;
            n1 = F.numerator;

            F.denominator = (d1 * pos) + d2;
            d2 = d1;
            d1 = F.denominator;
        }
    });

    //flip the fraction back over to format the correct output.
    F.numerator = d1;
    F.denominator = n1;
}

// creates a fraction from the decimal component
// insures its in its abs form to ease calculations.

void fraction::make_fraction() {

    size_t count = slen.get_decimal_length();
    long long n_dec = decimal;
    long long exp = (long long)pow(10, count);

    Euclids_method(n_dec, exp);
    convert(C.coef);
}

std::string get_w(const std::string& s) 
{
    std::string st = "0";
    std::string::size_type pos;
    pos = s.find(".");
        if (pos - 1 == std::string::npos) {
            st = "0";
            return st;
        }
        else { st = s.substr(0, pos);
        return st;
        }

    if (!(s.find("."))){
            st = "0";
        return st;
    }
    return st;
 }

std::string get_d(const std::string& s)
{ 
    std::string st = "0";
    std::string::size_type pos;
        pos = s.find(".");
        if (pos == std::string::npos) {
            st = "0";
            return st;
        }
        std::string sub = s.substr(pos + 1);
            st = sub;
                size_t sub_len = sub.length(); 
                    slen.set_decimal_length(sub_len);
        return st;
}

void fraction::ctf(double& nn)
{
        //using stringstream for conversion to string
        std::istringstream is;
        is >> nn;
        std::ostringstream os;
        os << std::fixed << std::setprecision(14) << nn;

        std::string s = os.str();

        is_negative = false; //reset for loops
        C.coef.erase(C.coef.begin(), C.coef.end()); //reset for loops

        long double n = 0.0;
        int m = 0;

        //The whole number part will be seperated from the decimal part leaving a pure fraction.
        //In such cases using Euclids agorithm would take the reciprocal 1/(n/exp) or exp/n.
        //for pure continued fractions the cf must start with 0 + 1/(n+1/(n+...etc
        //So the vector is initilized with zero as its first element.

        C.coef.push_back(m);
        std::cout << '\n';
    
        if (s == "q") { // for loop structures
            exit(0);
        }

        if (s.front() == '-') { // flag negative values. 
            is_negative = true; // represent nagative in output
            s.erase(remove(s.begin(), s.end(), '-'), s.end()); // using abs
        }

        // w, d, seperate the string components
        std::string w = get_w(s); 
        std::string d = get_d(s);

        try
        {
            if (!(n = std::stold(s))) {throw invalid(); } // string_to_double()
            get_fraction(w, d, n);
        } 
        catch (std::exception& e) {
            std::cout << e.what();
            std::cout <<'\n'<< std::endl;
        }
}

// The ostream formats and displays the various outputs

std::ostream& operator<<(std::ostream& os, fraction& f) 
{
    std::cout << '\n';
    if (f.is_negative == true) {
        os << "The coefficients are [" << '-' << f.whole << ";";
            for (size_t i = 1; i < C.coef.size(); ++i) {
                os << C.coef[i] << ',';
            }
            std::cout << "]" << '\n';
        os << "The cf is: " << '-' << f.whole;
            for (size_t i = 1; i < C.coef.size(); ++i) {
                os << "+1/(" << C.coef[i];
            }
            for (size_t i = 1; i < C.coef.size(); ++i) {
                os << ')';
            }
            std::cout << '\n';

        if (F.value >= 1 && F.numerator == 0 && F.denominator == 1) {
            F.numerator = abs(f.whole);
                os << '-' << F.numerator << '/' << F.denominator << '\n';
                return os;
        }
        else if (F.value == 0 && F.numerator == 0 && F.denominator == 1) {
                os << F.numerator << '/' << F.denominator << '\n';
                return os;
        }
        else if (F.value == 0 && F.numerator != 0 && F.denominator != 0) {
                os << '-' << abs(F.numerator) << '/' << abs(F.denominator) << '\n';
                return os;
        }
        else if (F.numerator == 0 && F.denominator == 0) {
                os << '-' << f.whole << '\n';
                return os;
        }
        else
                os << '-' << (abs(f.whole) * abs(F.denominator) + abs(F.numerator)) << '/' << abs(F.denominator) << '\n';
    }

    if (f.is_negative == false) {

        os << "The coefficients are [" << f.whole << ";";
             for (size_t i = 1; i < C.coef.size(); ++i) {
                os << C.coef[i] << ',';
            }
            std::cout << "]" << '\n';
        os << "The cf is: " << f.whole;
            for (size_t i = 1; i < C.coef.size(); ++i) {
                os << "+1/(" << C.coef[i];
            }
            for (size_t i = 1; i < C.coef.size(); ++i) {
                os << ')';
            }
            std::cout << '\n';

        if (F.value >= 1 && F.numerator == 0 && F.denominator == 1) {
            F.numerator = abs(f.whole);
                os << F.numerator << '/' << F.denominator << '\n';
                return os;
        }
        else if (F.value == 0 && F.numerator != 0 && F.denominator != 0) {
                os << abs(F.numerator) << '/' << abs(F.denominator) << '\n';
                return os;
        }
        else if (F.numerator == 0 && F.denominator == 0) {
            os << f.whole << '\n';
            return os;
        }
        else
            os << (abs(f.whole) * abs(F.denominator) + abs(F.numerator)) << '/' << abs(F.denominator) << '\n';

            os << f.whole << ' ' << F.numerator << '/' << F.denominator << '\n';
    }
    return os;
}

int main() 
{
    fraction f;
    double s = 0;
    std::cout << "Enter a number to convert to a fraction\n";
    std::cout << "Enter a \"q\" to quit\n";
    // uncomment for a loop

    while (std::cin >> s) {
        f.ctf(s);
        std::cout << f << std::endl;
    }

    // comment out these lines if you want the loop

    //std::cin >> s; 
    //f.ctf(s);
    //std::cout << f << std::endl;
 }

0

我完全同意dxivsolution,但我需要一个更通用的函数(我加了带符号的内容只是为了好玩,因为我的使用情况只包括正值):

#include <concepts>

/**
 * \brief Multiply two numbers together checking for overflow.
 * \tparam T The unsigned integral type to check for multiplicative overflow.
 * \param a The multiplier.
 * \param b The multicland.
 * \return The result and a value indicating whether the multiplication 
 *         overflowed.
 */
template<std::unsigned_integral T>
auto mul_overflow(T a, T b) -> std::tuple<T, bool>
{
    size_t constexpr shift{ std::numeric_limits<T>::digits / 2 };
    T constexpr mask{ (T{ 1 } << shift) - T{ 1 } };
    T const a_high = a >> shift;
    T const a_low = a & mask;
    T const b_high = b >> shift;
    T const b_low = b & mask;

    T const low_low{ a_low * b_low };
    if (!(a_high || b_high))
    {
        return { low_low, false };
    }

    bool overflowed = a_high && b_high;
    T const low_high{ a_low * b_high };
    T const high_low{ a_high * b_low };

    T const ret{ low_low + ((low_high + high_low) << shift) };
    return
    {
        ret,
        overflowed
        || ret < low_low
        || (low_high >> shift) != 0
        || (high_low >> shift) != 0
    };
}

/**
 * \brief Converts a floating point value to a numerator and
 * denominator pair.
 *
 * If the floating point value is larger than the maximum that the Tout
 * type can hold, the results are silly.
 *
 * \tparam Tout The integral output type.
 * \tparam Tin The floating point input type.
 * \param f The value to convert to a numerator and denominator.
 * \return The numerator and denominator.
 */
template <std::integral Tout, std::floating_point Tin>
auto to_fraction(Tin f) -> std::tuple<Tout, Tout>
{
    const Tin multiplier
    {
        std::pow(std::numeric_limits<Tin>::radix, 
                 std::numeric_limits<Tin>::digits)
    };
    uint64_t denominator{ static_cast<uint64_t>(multiplier) };
    int power;
    Tout num_fix{ 1 };
    if constexpr (std::is_signed_v<Tout>)
    {
        num_fix = f < static_cast<Tin>(0) ? -1 : 1;
        f = std::abs(f);
    }

    uint64_t numerator
    {
        static_cast<uint64_t>(std::frexp(f, &power) * multiplier)
    };
    uint64_t const factor
    {
        static_cast<uint64_t>(std::pow(
            std::numeric_limits<Tin>::radix, std::abs(power)))
    };
    if (power > 0)
    {
        while(true)
        {
            auto const [res, overflow]{ mul_overflow(numerator, factor) };
            if (!overflow)
            {
                numerator = res;
                break;                    
            }
            numerator >>= 1;
            denominator >>= 1;
        }
    }
    else
    {
        while (true)
        {
            auto const [res, overflow]{ mul_overflow(denominator, factor) };
            if (!overflow)
            {
                denominator = res;
                break;
            }
            numerator >>= 1;
            denominator >>= 1;
        }
    }

    // get the results into the requested sized integrals.
    while ((numerator > std::numeric_limits<Tout>::max()
            || denominator > std::numeric_limits<Tout>::max())
           && denominator > 1)
    {
        numerator >>= 1;
        denominator >>= 1;
    }

    return 
    {
        num_fix * static_cast<Tout>(numerator),
        static_cast<Tout>(denominator)
    };
}

你可以这样调用:

auto [n, d] { to_fraction<int8_t>(-124.777f) };

你会得到n=-124d=1

auto [n, d] { to_fraction<uint64_t>(.33333333333333) };

给出 n=6004799503160601d=18014398509481984


0
我针对这个问题想出了一个算法,但我认为它太冗长了,可以用更少的代码行来完成。抱歉缩进不好,因为在溢出时尝试对齐所有内容很困难。
#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("."    ((decimalNumber.length() -1) )); // store the value after the decimal into a valueAfterPoint 

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 by multiples of ten as long as the length is above zero of the decimal

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 position 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);

  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 themax        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;
 } } }   

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接