Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting a Decimal to a Fraction

I'm working on a "toy problem" where I am supposed to write a JavaScript function that converts a decimal into a fraction and returns it as a string. For example: fractionConverter(2.75) should return "11/4".

Here is my code:

function fractionConverter (number) {
  if (number > 0) {
    var isNegative = false;
  } else if (number < 0) {
    var isNegative = true;
  }

  number = Math.abs(number);

  if (number % 1 === 0) {
    var finalFrac = number + "/1";
  } else {
    for (var i = 2; i < 10000000000; i++) {
      if ((i * number) % 1 === 0) {
        var finalFrac = (i * number) + "/" + i;
      }
      if (finalFrac) { break; }
    }
  }

  var getFrac = function(numString, bool) {
    if (!bool) {
      return numString;
    } else {
       return "-" + numString;
    }
  }

  return getFrac(finalFrac, isNegative);
}

Sorry about the formatting. Anyway, I'm getting a weird spec failure. The function returns the correct values for the following numbers: 0.5, 3, 2.5, 2.75, -1.75 and .88. For some reason, however, it is failing on 0.253213. It is returning 1266065/5000000 instead of 253213/1000000. Not really sure why.

Thanks

like image 756
user3143105 Avatar asked Feb 07 '23 21:02

user3143105


2 Answers

I am just improving @william's answer, I think this script gives you more reduced fraction.

function fractionConverter(number) {
  var fraction = number - Math.floor(number);
  var precision = Math.pow(10, /\d*$/.exec(new String(number))[0].length);
  var getGreatestCommonDivisor = function(fraction, precision) {
    if (!precision)
      return fraction;
    return getGreatestCommonDivisor(precision, fraction % precision);
  }
  var greatestCommonDivisor = getGreatestCommonDivisor(Math.round(fraction * precision), precision);
  var denominator = precision / getGreatestCommonDivisor(Math.round(fraction * precision), precision);
  var numerator = Math.round(fraction * precision) / greatestCommonDivisor;

  function reduce (numer,denom) {
    for (var i = 2; i >= 9; i++) {
      if ((numer%i===0) && (denom%i)===0) {
        numerator=numer/i;
        denominator=denom/i;
        reduce(numerator,denominator);
      };
    };
  }
reduce(numerator,denominator);
  return numerator + "/" + denominator;
}

document.getElementById("output").innerHTML = fractionConverter(0.24888);

Here is the HTML

<body>
  <p id="output"></p>
</body>

</html>
like image 83
sarath Avatar answered Feb 10 '23 11:02

sarath


Javascript doesn't deal with floating point numbers accurately.

I tried typing this into node:

0.253213 * 1000000

And I got this:

253213.00000000003

Here is a different approach to testing for a multiplier

var bigNumber = Math.pow(10,8);

var isDivisible = (Math.round(i * number * bigNumber)/bigNumber % 1) == 0;

This will help you some of the way.

This also work the way you might expect it to, if you wanted 0.333333333 to be treated as 1/3.

One issue is that the highest integer you can have is javascript is between 10^15 and 10^16.

If ((number * bigNumber) > 2^53) this will not work.

like image 34
Andrew Shepherd Avatar answered Feb 10 '23 12:02

Andrew Shepherd