The following is the problem to which I am attempting a solution (in fact I have found the solution, there's a small doubt in a concept):-

Q4) Given a floating point number, write a program to convert it into its lowest irreducible
fractional form.
Note that the total number of digits before and after the decimal are less than 4, but greater than
0 (i.e there is at least one digit before the decimal and at least one digit after the decimal).
Sample Input:
3
2.4
2.5
3.2
Sample Output:
12/5
5/2
16/5

under the following constraints:-

General Instructions:
1) Every input starts with a number ‘n’, where ‘n’ are the total number of test cases that will be
followed, for eg. in Q1) n = 5, means that there are n test cases for this question, those are, 3,
60, 100, 1024, 23456.
2) Use of Arrays or any other advanced data structure isn’t allowed
3) Don’t use any pre-defined function in C library.

My first attempt for the solution was this:-

include<stdio.h>

int main()
{
    double p;
    int n,i,j,denominator=1;
    long int numerator;
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        scanf("%lf",&p);
        numerator=p*10000;
        denominator=10000;
        for(j=5000;j>0;j--)
        {
            if(numerator%j==0 && denominator%j==0)
            {
                numerator/=j;
                denominator/=j;
            }
        }
        printf("%ld/%d\n",numerator,denominator);
    }

    return 0;
}

This one produced disastrous results as the code had absolutely no regards for data types.
When I put the input as "3.4", it produced the output of:- "33999/10000".
Though when I put the input as "5.2", it produced the correct output of:- "5/2".
Why this biased behaviour? I mean shouldn't the output have been "51999/10000".

Anyways, for my second attempt I tried this:-

#include<stdio.h>

int main()
{
    double p,numerator;
    int n,i,j,denominator=1;
    long int numerator1;
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        scanf("%lf",&p);
        numerator=p*10000;
        printf("numerator=%lf\n",numerator); //for debugging purposes
        numerator1= (long int) numerator;
        printf("numerator1=%ld\n",numerator1);// for debugging purposes
        denominator=10000;
        for(j=5000;j>0;j--)
        {
            if(numerator1%j==0 && denominator%j==0)
            {
                numerator1/=j;
                denominator/=j;
            }
        }
        printf("%ld / %d",numerator1,denominator);
    }

    return 0;
}

Now outputs for this one was even weirder. I tried quite a lot of inputs, and the output seemed perfectly fine until I randomly tried "1.2972". IT produced the output:- " 12971/10000".
This program was correctly printing the outputs for larger numbers than 1.2972 like 8976.7642 whose output was:- "44883821 / 5000".
What's the problem with the conversion? Why is the program working for some numbers and not for the others?

Anyways, this is my final attempt which hasn't presented any incorrect outputs so far.

#include<stdio.h>

int main()
{
    long double p,numerator;
    int n,i,j,denominator=1;
    long int numerator1;
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        scanf("%Lf",&p);
        numerator=p*10000;
        numerator1= (long int) numerator;
        denominator=10000;
        for(j=5000;j>0;j--)
        {
            if(numerator1%j==0 && denominator%j==0)
            {
                numerator1/=j;
                denominator/=j;
            }
        }
        printf("%ld/%d\n",numerator1,denominator);
    }

    return 0;
}

The only change I made in this program was changing the data type of numerator from "double" to "long double". NOw, though I havent encountered any incorrect outputs doesnt necessarily mean that it wont produce incorrect output for any other input as well. And I guess the only way I can be sure of my program is if I can understand this weird behaviour by data types and their aversion to conversion.

If anyone could help me, I'd be really really really obliged. :)

Recommended Answers

All 2 Replies

I suggest this way. It's just the way I'd do it by hand, with paper and pencil.

Get the floating point number, and if it has one digit after the decimal, multiply it by 10:

numerator = 52 (5.2 * 10)
denominator = 10

Now work in your loop, to see what can evenly divide into both the numberator, and the denominator. If both % 2 = 0, (as here), then divide them by 2, so you have

26/5ths, which is irreducible.

The % operator (modulus) operator is what you want to use to find out if there is any remainder from a division operation.

Your loop needs to check from 2 up to the smaller (either numerator or denominator).

If your original number has 2 digits after the decimal place, then you'll want to multiply by 100, and use 100 as your denominator. For 3 digits after the decimal place, multiply by 1000, etc.

Which is fine and good, but without using an array or some other struct, I'm not sure how to find out the number of digits after the decimal place, in the given numbers.

Seems awkward, but OK: (a thought, not tried)
You have to get your MAX_(data type), and make sure that your multiplication doesn't exceed it. That could give you negative numbers (use unsigned for this to extend the range of your integral type (long, or long long).

Multiply it by the power of 10 that just allows the given numbers to both stay below the MAX_ number (include <limits.h> and possibly other headers, check your compiler for the macro MAX_ULONG, or MAX_UL).

Then start the big division by loop for numerator and denominator, and keep going until you reach the final irreducible value. Use % (mod arithmetic), of course.

Sorry this is rather rambling.

@Adak...
Firstly, thanks for taking out the time to reply. :)

THat is the approach that I had tried at first. To find the number of digits after decimal point I wanted to check divisibility by .0001, .001, .01 and .1 . But I found out that % operator did not work with floating points. I couldn't use fmod() since I am not allowed to use any in built functions. ANyways, since the question said that the number of decimal points won't exceed 4, that's why I multiplied it by 10000.

Now, I don't think that the problem is with max limit or anything coz the program's not working for, lets say, 1.2972 but it is working for numbers "larger" than that as I have already specified in the original post.

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.