Jump to content

C++, issues converting decimal to fraction

- - - - -

This topic has been archived. This means that you cannot reply to this topic.
5 replies to this topic

#1
alpha_gamma

alpha_gamma

    Newbie

  • Members
  • Pip
  • 2 posts
Hi all,

I am working on a C++ program that converts a decimal to a fraction, finds the lowest common multiple, multiplies the numerator by the denominator, then reduces the fraction again so the fraction will be 'numerator/1'.

I am using this code in a larger program to change a floating point slope value to a whole value for slope-intercept equations and standard form equations.

The program will run but I tested almost 500 numbers and 20 numbers made the program crash (it stalled and did not finish the equation, I had to close the terminal and open it up again... )

These 20 numbers I had problems with:

2.36, 7.36, 1.11, 1.001, 1.66, 1.88, 2.22, 2.13, 3.24, 3,26, 3.32, 3.43, 3.49, 3.51, 3.57, 3.68, 3.74, 3.76, 3.82

(I am sure there are more...)

I have tried c-style casting and dynamic and static casting to try to resolve this issue. Can someone help me out and point out why these certain numbers make the program crash and offer a possible sloution?

I tried debugging this program on gdb and keep on getting this frustrating message..

(gdb) break 16
No line 16 in file "init.c".
(gdb)


Here is the program's code, I also attached the program files in a zip package:



//example.cc

#include <iostream>

#include "reduce.h"

#include "decimal-to-fraction.h"

using namespace std;


int main()

{

	double deci;

	double n, d;


	while(1) {

		cout << "Enter a decimal to convert to a fraction ('0' to quit): ";

		cin >> deci;

		cin.ignore(INT_MAX, '\n');

		if(!deci) exit(0);

		

		dec_to_frac(deci, n, d);

		

		if (n * d != n){

			cout << '\n' << deci << " = " << n << '/' << d << "\n\n";

			cout<<'\n' << d << " x " << n;

			n = d * n;

			cout<< " = " << n << "\n\n";

			cout<<'\n' << n << '/' << d; 

			reduce(n, d);

		

			cout << " = " << n << '/' << d << "\n\n";


			cout<<'\n' << n << "\n\n";

		}

		

		else

			cout<<'\n' << deci<< "\n\n";

	

	}


	return 0;

}


#ifndef _REDUCE_H_


#error You must include "reduce.h" before this file


#endif /* def _REDUCE_H_ */




#ifndef _DECIMAL_TO_FRACTION_H_


#define _DECIMAL_TO_FRACTION_H_




void dec_to_frac(double decimal, double &numerator, double &denominator)


{


	//numerator = static_cast<int >(decimal);

	//numerator = (int )decimal;

	numerator = decimal;


	denominator = 1;

	



	while(numerator != (int)numerator) {


		numerator *= 10;


		denominator *= 10;


	}


	reduce(numerator, denominator);


}




#endif /* def _DECIMAL_TO_FRACTION_H_ */


#ifndef _REDUCE_H_


#define _REDUCE_H_




void reduce(double &numer, double &denom)


{


	int i;




	for(i=2; i<=numer; ++i) {

		


		if( ((numer/i) == ((int )(numer/i))) && ((denom/i) == ((int)(denom/i))) ) {


			numer /= i;


			denom /= i;


			--i;              


		}


	}


}




#endif /* def _REDUCE_H_ */

Attached Files



#2
CygnetGames

CygnetGames

    Programmer

  • Members
  • PipPipPipPip
  • 119 posts
I may be completely off the mark here, but in your declaration of dec_to_frac, you say:

void dec_to_frac(double decimal, double &numerator, double &denominator)

but they you use numerator like:

numerator *= 10;

Do you want to instead do:

void dec_to_frac(double decimal, double *numerator, double *denominator)

...

*numerator *= 10;

...

Then of course you would have to change the other references to numerator and denominator in this function.

#3
v0id

v0id

    Retired

  • Members
  • PipPipPipPipPipPipPipPipPip
  • 2,936 posts
Cygnet, his code at that point is right. He is receiving the variable as a reference, and then it's okay to do what he does. A small example:
void foo(int &x) { x++; }
// ...
int y = 1;
foo(y);
printf("y = %d\n", y); // 2

Alpha, what do you exactly trying to do. I'm not a math genius, and don't know much about what you're trying to do. Can you come with some examples, as how it's supposed to do.
// Is it something like this you want to do (just a step in the dark)

 100 =>  1.00
 200 =>  2.00
 350 =>  3.50
1000 => 10.00
1234 => 12.34
Maybe this is completely wrong, but I don't understand what you're trying to do :-)

#4
WingedPanther

WingedPanther

    A spammer's worst nightmare

  • Moderators
  • 16,831 posts
Another, more subtle, issue that can cause you problems is this: When you enter a value, like 2.36, it is not necessarily stored in that format in memory. As a result, you may be working with a value like 2.359999999999999999999999. I would strongly urge you to work with the decimal value as a string, to avoid internal representation bugs like this one.
Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

#5
alpha_gamma

alpha_gamma

    Newbie

  • Members
  • Pip
  • 2 posts
Thank you for your replies...

v0id:

I am using this algorithm in a larger program in which a user types in an ordered pair of coordinates and the program will calculate linear functions and values based on the ordered pair, the slope: slope,distance, midpoint, y-intercept, x-intercept, two point slope equations, a slope-intercept equation and a standard form equation.

In a slope-intercept equation (y=mx+b, m being the slope) the slope must be a whole number, not a fraction or floating point number. In a standard form equation (ax+by+c=0) the value for 'a' must be a whole number as well to be an academically correct textbook solution.


Your method of changing the decimal to fraction is one solution but I am trying to use the algorithm of converting the decimal to a fraction, then reducing it to the least common multiple. Multiply the numerator by the denominator and then reduce again to the lowest common multiple. Some algebra textbooks present that method as well as the one you mentioned. I think that the fraction to lowest common multiple problem is very interesting and is a good study in robust code...


WingedPanther:

As mentioned above, I am using this algorithm in a larger program for a calculated double value, so for the case study I have to keep the user input as a numeric primitive type.

I will put a loop limiter in the while loop instead of having being a while(1) loop to prevent the infinite loop from happening. The problem is that as you mentioned with the inaccurate binary representation, the two double values can't be compared. I should change the 'numerator' and 'denominator' value to integer values instead of double values or round the decimal places down to at least three places...

Regards,

Andrew

#6
jvclark

jvclark

    Newbie

  • Members
  • Pip
  • 5 posts
If you reduce the fraction to numerator/1 then you will end up with the number you started with no matter how you reduce it.
If you drive fast enough towards a red light it will appear green.