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?

Recommended Answers

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.