【问题标题】:Converting a Decimal to a Fraction将小数转换为分数
【发布时间】:2016-01-29 04:49:16
【问题描述】:

我正在研究一个“玩具问题”,我应该编写一个 JavaScript 函数,将小数转换为分数并将其作为字符串返回。例如:fractionConverter(2.75) 应该返回“11/4”。

这是我的代码:

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);
}

对格式问题感到抱歉。无论如何,我遇到了一个奇怪的规范失败。该函数返回以下数字的正确值:0.5、3、2.5、2.75、-1.75 和 .88。然而,由于某种原因,它在 0.253213 上失败了。它返回 1266065/5000000 而不是 253213/1000000。不太清楚为什么。

谢谢

【问题讨论】:

  • 那是因为0.253213 * 1000000 === 253213.00000000003。见Is floating point math broken?
  • 不仅不能用小数准确表示所有分数,ECMAScript 的number values 也不能准确表示所有小数。
  • 好的,我投票重新提出这个问题。考虑到浮点数的限制,我想知道解决这个特定问题的最佳方法。
  • @AndrewShepherd—好的,你说得有道理。一定有比 1.0e10 循环更好的方法。 ;-)

标签: javascript numbers decimal fractions


【解决方案1】:

我只是在改进@william 的答案, 我认为这个脚本给你更多的减少分数。

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);

这里是 HTML

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

</html>

【讨论】:

    【解决方案2】:

    Javascript 不能准确地处理浮点数。

    我尝试在节点中输入这个:

    0.253213 * 1000000
    

    我得到了这个:

    253213.00000000003
    

    这是测试乘数的另一种方法

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

    这将对您有所帮助。

    如果您希望 0.333333333 被视为 1/3,这也可以按照您预期的方式工作。

    一个问题是您可以拥有的最大整数是 javascript 在 10^15 和 10^16 之间。

    如果 ((number * bigNumber) > 2^53) 这将不起作用。

    【讨论】:

    • 谢谢。 isDivisible 的东西起作用了,虽然我不确定我明白为什么。我们创建一个巨大的数字,然后将其乘以数字和 i,然后将该数字四舍五入,因为出于某种我不明白的原因,JavaScript 将返回一个小数而不是整数。然后我们通过将舍入值除以 bigNumber 来抵消我们的大数字,并检查 那个 值是否可以被 1 整除。真是一团糟。
    【解决方案3】:

    这个答案的警告是 ECMAscript 不能充分处理小数。 另外,请注意,以下内容大部分是伪代码,但应该可以进行一些小的修复。

    这里是这个问题的 javascript 解决方案:

    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()
    

    如果您好奇,这里有一个 Python 解决方案:

    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()
    

    【讨论】:

      【解决方案4】:

      我完全改变了您的代码结构,但这个解决方案确实有效。它基于来自this 线程的代码。我希望这会有所帮助。

      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>

      【讨论】:

        【解决方案5】:

        您可以使用 Erik Garrison 的 fraction.js 库来执行此操作以及更多的分数运算。

        要做 1.75 ,你可以做

        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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-10-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-08-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多