最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Converting a Decimal to a Fraction - Stack Overflow

programmeradmin3浏览0评论

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

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

Share Improve this question edited Jan 29, 2016 at 7:31 sarath 3438 silver badges31 bronze badges asked Jan 29, 2016 at 4:49 user3143105user3143105 1292 silver badges12 bronze badges 4
  • 2 That's because 0.253213 * 1000000 === 253213.00000000003. See Is floating point math broken? – Oriol Commented Jan 29, 2016 at 4:59
  • 1 Not only is it impossible to represent all fractions accurately using decimals, ECMAScript's number values can't accurately represent all decimal numbers either. – RobG Commented Jan 29, 2016 at 4:59
  • OK, I am voting to reopen this question. I want to know the best way to approach this particular problem, given the limitations of floating point numbers. – Andrew Shepherd Commented Jan 29, 2016 at 5:02
  • @AndrewShepherd—Ok, you have a point. There's gotta be a better way than a 1.0e10 loop. ;-) – RobG Commented Jan 29, 2016 at 5:05
Add a ment  | 

5 Answers 5

Reset to default 3

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>

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.

The caveat to this answer is that ECMAscript inadequately handles Decimals. Also, note that the following is largely pseudocode, but should work with minor fixes.

Here is a javascript solution to this problem:

var decimal_to_fraction = {
  "numerator": 0,
  "denominator": 0,
  "simplified_numerator": this.numerator,
  "simplified_denominator": this.denominator,
  "init": function(numerator, denominator){
    this.numerator = numerator
    this.denominator = denominator
  },
  "get_divisor": function(numerator, denominator){
    var divisor = 0;
    var divisors = [1, 2, 3, 4, 5];

    for (i in divisors) {
      if (!(numerator % divisor) && !(denominator % divisor)) {
        divisor = i;
        break
      }
    }

    return divisor
  },
  "calculate_fraction": function() {
    var simplified = false;
    divisor = this.get_divisor(numerator_denominator);

    if (divisor) {
      while (simplified == false) {
        if (this.simplfieid_numerator / divisor and this.simplified_denominator / divisor) {
          this.simplified_numerator = simplified_numerator / divisor
          this.simplified_denominator = simplified_denominator / divisor
        } else {
          simplified = true
        }
      }
    }

    return (this.simplified_numerator, this.simplfieid_denominator)
  },
  "get_fraction": function() {
    this.calculate_fraction()

    fraction = "{0} / {1}".format(this.simplfieid_numerator, this.simplified_denominator"

    return fraction
  }

}

decimal_to_fraction.get_fraction()

In case you were curious, here's a Python solution to your problem:

class DecimalToFraction(object):
    def __init__(decimal):
        self.numerator = decimal * 100
        self.denominator = 100
        self.simplified_numerator = self.numerator
        self.simplified_denominator = self.denominator

    def get_divisor(self, numerator, denominator):
        divisor = 0

        for i in range(0,5):
            if not numerator % divisor and not denominator % divisor:
                divisor = i
                break

        return divisor

    def calculate_fraction(self):
        simplified = False

        divisor = get_divisor(self.numerator, self.denominator)

        if divisor:
            while simplified == False:
                if self.simplified_numerator / divisor and self.simplfieid_denominator / divisor:
                    self.simplified_numerator = simplified_numerator / divisor
                    self.simplified_denominator = simplified_denominator / divisor
                else:
                    simplified = True

        return (self.simplified_numerator, self.simplified_denominator)


    def get_fraction(self):
        self.calculate_fraction()

        fraction = "{0} / {1}".format(self.simplified_numerator, self.simplified_denominator)

        return fraction


#d2f = DecimalToFraction(<decimal>)
#d2f.get_fraction()

I pletely changed the structure of your code, but this solution does work. It is based off of code from this thread. I hope this helps.

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 / greatestCommonDivisor;
  var numerator = Math.round(fraction * precision) / greatestCommonDivisor;

  return numerator + "/" + denominator;
}

document.getElementById("output").innerHTML = fractionConverter(0.253213);
<!DOCTYPE html>
<html>

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

</html>

You can use Erik Garrison's fraction.js library to do that and more fractional operations.

To to do 1.75 , you can just do

var f = new Fraction(1.75);
console.log(f.toFraction()); // Results "1 3/4" 
console.log(f.s * f.n + " / " + f.d); // Results "7 / 4"
console.log(f.toString()); // Results "1.75
发布评论

评论列表(0)

  1. 暂无评论