How to retain fraction form, not decimal of division

Jun 16, 2014 at 5:16am
I need to set something up whereby the result of 10/4 = 10/4, not 2.5. Basically if the result isn't an integer, I need my calculation to remain as an integer, even if that means it remains as a fraction.

www.sagemath.com equations seem to permit this, but I can't seem to get C++ to do that. The conversion to decimal keeps screwing up my equations.

Only solution I've found is semi-complicated and adds additional calculations I don't need.

Currently my divisions are resulting in 0 (because I'm using 256 and 512 bit integers).
Last edited on Jun 16, 2014 at 5:16am
Jun 16, 2014 at 5:36am
You will have to make a fraction class. Shouldn't be too trivial. Or you could even just make a division function. Something like:

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
void simplify(int &numerator, int &denominator)
{
    int max = numerator > denominator ? numerator : denominator;
    for(int i = max; i > 1; --i) //no need to check if divisible by 1
   {
        if(!(numerator % i) && !(denominator % i)) //divides evenly into both
       {
            numerator /= i;
            denominator /= i;
            break;
       }
   }
}
std::string divide(int numerator, int denominator)
{
    simplify(numerator, denominator); //put in reduced form
    if(!(numerator % denominator)) //if there is no remainder
    {
        numerator /= denominator;
    }
    std::stringstream ss;
    if(denominator > 1)
    {
        ss << numerator << "/" << denominator;
    }
    else
    {
        ss << numerator;
    }
    return ss.str();
}




here is a demo version:
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
#include <iostream>
#include <string>
#include <sstream>

void simplify(int &numerator, int &denominator)
{
    int max = numerator > denominator ? numerator : denominator;
    for(int i = max; i > 1; --i) //no need to check if divisible by 1
   {
        if(!(numerator % i) && !(denominator % i)) //divides evenly into both
       {
            numerator /= i;
            denominator /= i;
            break;
       }
   }
}
std::string divide(int numerator, int denominator)
{
    simplify(numerator, denominator); //put in reduced form
    if(!(numerator % denominator)) //if there is no remainder
    {
        numerator /= denominator;
    }
    std::stringstream ss;
    if(denominator > 1)
    {
        ss << numerator << "/" << denominator;
    }
    else
    {
        ss << numerator;
    }
    return ss.str();
}

int main()
{
    int numerator;
    int denominator;
    char junk;
    while(std::cout << "Please enter fraction: " && std::cin >> numerator >> junk >> denominator)
    {
        std::cout << numerator << junk << denominator << " = " << divide(numerator, denominator) << std::endl;
    }
}


PS I coded pretty fast so it's probably not very neat, efficient, and may have bugs.


[edit]added the missing '[' in code tags.[/edit]
Last edited on Jun 16, 2014 at 5:41am
Jun 16, 2014 at 8:30am
I think you've got a good idea, but I still need to be able to use these fractions with other equations in the program such that they never fully divide unless I'm working with only an integer. As soon as I re-apply your code, I think it'd simplify.
Jun 16, 2014 at 1:50pm
You might want to consider a library created for this kind of numerical work:

https://gmplib.org/

This may apply to your needs:
https://gmplib.org/manual/Rational-Number-Functions.html#Rational-Number-Functions

And converting to basic types:
https://gmplib.org/manual/Rational-Conversions.html#Rational-Conversions
Jun 16, 2014 at 2:55pm
Using boost::rational<> would feel a whole lot more like programming in C++.
http://www.boost.org/doc/libs/1_55_0/libs/rational/rational.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>

template < typename INTEGER_TYPE = int > using rational = boost::rational<INTEGER_TYPE> ;

int main()
{
    rational<> a = 7 ; // 7/1
    rational<> b( 44, 14 ) ; // 22/7
    rational<> c = a*a + b*b - 2*a*b ;
    std::cout << a << '\n' << b << '\n' << c << '\n' ;
    
    using boost::multiprecision::cpp_int ;
    rational<cpp_int> d( cpp_int("12345678987654321"), cpp_int("123456789") ) ;
    std::cout << d << '\n' << d + 25000000 << '\n' ;
    
    std::cout << d / boost::rational_cast<cpp_int>(c) << '\n' ;
}

g++-4.8 -std=c++11 -O2 -Wall -Wextra -pedantic-errors main.cpp && ./a.out
7/1
22/7
729/49
1371742109739369/13717421
1714677634739369/13717421
1371742109739369/192043894

http://coliru.stacked-crooked.com/a/f7945b172844733b
Jun 16, 2014 at 7:21pm
JLBorges, That was perfect! (EDIT: removed questions etc that I was able to answer for myself)

How do I MOD this number and or convert it back into the "INTEGER_TYPE" it was before I rational<>'d it? When I make the same int = the rational<>'d number it throws an error.
Last edited on Jun 16, 2014 at 8:47pm
Jun 17, 2014 at 12:07am
1
2
3
4
5
6
7
8
boost::rational<int> r( 44, 14 ) ; // 22/7

int numerator = r.numerator() ;
int denominator = r.denominator() ;

double value = double(numerator) / denominator ;
int quotient = numerator / denominator ;
int remainder = numerator % denominator ;
Topic archived. No new replies allowed.