Hi,
I want to write a function that coverts a double number into its rational form. For example if the input number in 4.33 I must get numerator = 433 and denominator = 100.

Here is something I tried, it doesn't work because of floating point inaccuracy :

``````void ToRational( double d, int &numerator, int &denominator )
{
int n;
double dummy;
// Get the integral part
numerator = (int) num;
// Get the fractional part
double frac = modf( num, &dummy );

denominator = 1;

while( frac != 0.0 )     // This comparision will never work
{
frac *= 10;
denominator *= 10;

n = (int) frac;
frac = modf( num, &dummy );
numerator = numerator*10 + n;
}
}``````

Is there a solution?

## All 17 Replies

I'm probably missing some math aspect here, but couldn't you convert 4.33 to a string, find out what position the . is and have your answer?

``````double dNum = 4.33;
int iNum;
int DecPnt = 0;
for(int i=1; true; i*=10)
{
dNum*=i;
iNum=(int) dNum;
if (iNum==dNum) break;
DecPnt++;
}``````

I'm probably missing some math aspect here, but couldn't you convert 4.33 to a string, find out what position the . is and have your answer?

I also think that this is the simplest and ,the most accurate, answer. Great solution. :idea:

That is a great code, but it doesn't work for all cases. I've used your code with a a few modifications :

``````#include <iostream>
#include <cmath>
using namespace std;
#include <conio.h>

int main( )
{
double dNum;
int iNum;
int DecPnt = 0;
int i;
cin>>dNum;
double Denominator;
for( i=1; true; i*=10)
{
dNum*=i;
iNum=(int) dNum;
if (iNum==dNum) break;
DecPnt++;
}
iNum /= 10;
Denominator = pow( 10.0, (double)DecPnt );
cout<<iNum<<" / "<<Denominator;
getch( );
return 0;
}``````

This works really great for many cases like 4.33 ( output is 433 / 100 ), 5.65, etc. However it fails for a lot of cases like 4.56, 2.12, 45. :sad:
Could there be a general soln.that works for all cases?

You'll probably face the same problem( that of floating inaccuracy ) trying to convert a double to string. Give it a try, if you want.

Yes, that is better.

vicky_dev,

I'm still not sure what you want in terms of an answer. Is it basically 2 numbers that when divided end up with your original value? (ie 433 % 100 = 4.33?)

Well I ran a piece of code under a debugger. The value I entered was 0.0000124568 but the value stored by the program which I saw using the debugger was 1.2456800000000001e-005. You can see an unnecessary '1' marked in red. Since this is a problem due to the representation of floating point decimal numbers in binary, the only way I see to get around it is to enter the double value as a char array and search for the decimal point in the array. But even then you will have to know the maximum length of a value that can be entered.

:cheesy: Hi buddy,
i m just a beginner of 'C'.I tried solving ur problem & got out with the following code.It worked good for most of the values,but still it is havin' some problem of which i cann't find solution of... :idea:
#include<stdio.h>
#include<conio.h>
void main()
{
float n;
int a,d=1;
clrscr();
printf("\n Enter a rational no.=);
scanf("%f",&n);
a=n;
while((n-a)!=0)
{
n=n*10;
a=n;
d=d*10;
}
printf("\n numerator=%d,denominator=%d",a,d);
getch();
}

Hope it would be very simple to understand. :confused:

Try this one out:

``````#include <iostream>
#include <sstream>
using namespace std;
int main()
{
string numerator;
string denominator;
string myNum;
cout<<"Enter Number"<<endl;
cin>> myNum;
int pos=myNum.find( "." );
if ( pos == string::npos )
{
numerator = myNum;
denominator = 1;
}
else
{
int end = myNum.size();
numerator=myNum.erase(pos,1);
int diff = end - pos;
cout<<"POS is:"<<pos<< " location from end is:"<<diff<<endl;
denominator="1";
for ( int i=0;i< diff -1;i++)
{
denominator.append( "0" );
}
}
cout<<"NUMERATOR:"<<numerator<<" DENOMINATOR:"<<denominator<<endl;
return 0;
}``````

winbatch, your avatar is so cool!

winbatch, your avatar is so cool!

I claim no credit, it's one of daniweb's choices...

You are reading the double number as a string, which is not exactly what I'm looking for.

winbatch,
You are right, I do want two numbers, which when divided, give the double number. It is like the problem of determining the fraction (a/b form ) which is equivalent to the given float number.

anupam_smart,

That is probably the best possible solution under the circumstances. It works well for most cases. Great solution.

Hi everybody,
I guess the problem has no exact solution. But there could be an approximate solution.

Hey,

I got a lot of ideas from all of you and I think I found a good enough solution:

``````#include <iostream>
#include <cmath>
#include <conio.h>
using namespace std;

const double ACCURACY = 0.000001;   // This may be good enough

int main( )
{
double num;
int numerator, denominator = 1;

cout<<"Enter a double number: ";
cin>>num;

numerator = (int) num;

while( fabs( (double)numerator - num ) > ACCURACY )
{
num *= 10;
numerator = (int) num;
denominator *= 10;
}

cout<<"Fractional form: "<< numerator<<" / "<<denominator;

getch( );
return 0;
}``````

Thanks everyone, this forumserved its purpose allright.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.