首页 > 解决方案 > 带有简化分数的分数计算器

问题描述

我的代码有几个问题,虽然我已经尝试过了,但我还没有发现它有什么问题。这里是:

public class FracCalc {
    public static void main(String[] args) {
        // String to test
        //String input = "5_3/4 - 6_7/8 + 3/4";
        System.out.println(produceAnswer("-3_3/4 / -2_2/3"));
    }

    public static String produceAnswer(String input) {

        // Splits everything at every space
        String[] array = input.split(" ", 0);

        int allWholes = 0;
        int allNumerators = 0;
        int allDenominators = 1;

        // Multiplier is 1 or -1, 1 is add, -1 is subtract
        int multiplier = 1;
        // Operation mode; 0=+,-; 1=*; 2=/
        int mode = 0;

        // the for loop is used to identify and solve the the test
        for (int i = 0; i < array.length; i++) {
            String part = array[i];
            // 
            int whole = 0;
            int numerator = 0;
            int denominator = 0;

            // If it has a _, then it's a whole + fraction
            if (part.contains("_")) {

                // Convert Int from start of part (0) to the character before _, "55_30/40" -> 55

                whole = Integer.parseInt(part.substring(0, part.indexOf("_")));

                // Convert Int from the character AFTER _ to the character before /, "55_30/40" -> 30

                numerator = Integer.parseInt(part.substring(part.indexOf("_") + 1, part.indexOf("/")));

                // Convert Int from the character AFTER / to the end, "55_30/40" -> 40

                denominator = Integer.parseInt(part.substring(part.indexOf("/") + 1, part.length()));
            }
            // If no _, but still has a / AND it is not just the symbol "/", then it's just a fraction
            else if (part.contains("/") && part.length() != 1) {
                numerator = Integer.parseInt(part.substring(0, part.indexOf("/")));
                denominator = Integer.parseInt(part.substring(part.indexOf("/") + 1, part.length()));
            } //else if(part.contains("*") && part.contains("/")){}
            else if (part.contains("/") ) {
                mode = 2;
            }
            // TODO: Make multiplication

            // Negative sign(if number is negative)
            else if (part.contains("-")) {
                multiplier = -1;
            }
            // Positive sign(if number is positive)

            else if (part.contains("+")) {
                multiplier = 1;
            }
            // If neither _ nor /, then it's a whole
            else {
                whole = Integer.parseInt(part);
            }

            // Add all the wholes together
            allWholes += whole * multiplier;

            // If denom is the same
            if (denominator == allDenominators) {
                allNumerators += numerator * multiplier;
            }
            // If they're not the same
            else if (numerator != 0 && denominator != 0) {
                if (mode == 0 ) {
                    // Cross multiply
                    allNumerators *= denominator;

                    // Add
                    allNumerators += numerator * allDenominators * multiplier;


                    // Second part of cross multiply
                    allDenominators *= denominator;
                }
                // Multiplication
                else if (mode == 1) {

                    allDenominators *= denominator;

                    allNumerators *= numerator;

                }
                // Division
                else if (mode == 2) {
                    // Reverse multiply because (1/2)/(1/2) -> (1*1)/(2*2)
                    allNumerators = allNumerators * denominator;
                    allDenominators = allDenominators * numerator;
                }
            }
        }

        // Simplifies fraction by checking to see id the top is bigger than bottom
        // 9/4 -> 2_1/4


        while(allNumerators > allDenominators){
             allWholes = allNumerators / allDenominators;
             allNumerators %= allDenominators;
        }


        if (allWholes == 0) {
            return (allNumerators + "/" + allDenominators);
        }
        else if (allNumerators == 0 || allDenominators == 0) {
            return allWholes + "";
        }
        else {
            return allWholes + "_" + (allNumerators + "/" + allDenominators);
        }
    }
}

我的目标是制作一个带有简化答案的分数计算器(作为分数)。我很确定我的乘法、除法和简化 while 循环是问题所在。谢谢!

标签: javaarrayscalculator

解决方案


您的代码中有很多好的想法,但正如您所知,也存在问题。

  1. 试图跟踪计算中的整个部分会遇到很多麻烦。就像在小学数学中一样,使用整个部分来创建一个不正确的分数,方法是:

          numerator += whole*denominator;
    

    然后只需使用numeratorand进行数学运算,denominator并在完成所有计算后提取整个部分,您已经在执行此操作。

  2. 你解析负数的方式是错误的。此外,您应该删除使用multiplier并只使用负数numerator

  3. 如果您删除multiplier,那么您需要跟踪-+作为单独的操作,但这很容易做到。

  4. 在每次计算结束时,您应该通过以下方式确保结果 allDenominators为正:

        if (allDenominators < 0)
        {
          allNumerators = -allNumerators;
          allDenominators = -allDenominators;
        }
    

    这将阻止您输出 -3/-4

  5. 简化分数的方式并不完全正确。你有:

        while(allNumerators > allDenominators){
             allWholes = allNumerators / allDenominators;
             allNumerators %= allDenominators;
        }
    

    如果allNumerators == allDenominators,即答案应该是 1 怎么办?此外,一旦你完成allNumerators %= allDenominators了 while 循环中的条件,就不再是真的。只需这样做:

        if(allNumerators >= allDenominators){
             allWholes = allNumerators / allDenominators;
             allNumerators %= allDenominators;
        }
    
  6. 最后考虑实现一个更大的公约数(GCD)例程来简化你的分数,例如从48/1283/8

这是您的代码副本,其中包含上述大部分想法,但您可能应该先尝试自己修复它们,并且仅将其用作参考。

public class FracCalc
{
  public static void main(String[] args)
  {
    // String to test
    System.out.println(produceAnswer("5_3/4 - 6_7/8 + 3/4"));
    System.out.println(produceAnswer("-3_3/4 / -2_2/3"));
  }

  public static String produceAnswer(String input)
  {
    // Splits everything at every space
    String[] array = input.split(" ", 0);

    int allNumerators = 0;
    int allDenominators = 1;

    // Operation mode; 0=+; 1=-; 2=*; 3=/
    int mode = 0;

    // the for loop is used to identify and solve the the test
    for (int i = 0; i < array.length; i++)
    {
      String part = array[i];

      int numerator = 0;
      int denominator = 0;

      // If it has a _, then it's a whole + fraction
      if (part.contains("_"))
      {
        // Convert Int from start of part (0) to the character before _,
        // "55_30/40" -> 55

        int whole = Integer.parseInt(part.substring(0, part.indexOf("_")));

        // Convert Int from the character AFTER _ to the character before /,
        // "55_30/40" -> 30

        numerator = Integer.parseInt(part.substring(part.indexOf("_") + 1, part.indexOf("/")));

        // Convert Int from the character AFTER / to the end, "55_30/40" -> 40

        denominator = Integer.parseInt(part.substring(part.indexOf("/") + 1, part.length()));

        if (whole > 0)
          numerator += whole * denominator;
        else
          numerator = -numerator + whole * denominator;
      }
      // If no _, but still has a / AND it is not just the symbol "/", then it's
      // just a fraction
      else if (part.contains("/") && part.length() != 1)
      {
        numerator = Integer.parseInt(part.substring(0, part.indexOf("/")));
        denominator = Integer.parseInt(part.substring(part.indexOf("/") + 1, part.length()));
      } // else if(part.contains("*") && part.contains("/")){}
      else if (part.equals("/"))
      {
        mode = 3;
      }
      else if (part.equals("+"))
      {
        mode = 0;
      }
      else if (part.equals("-"))
      {
        mode = 1;
      }
      else if (part.equals("*"))
      {
        mode = 2;
      }
      // If neither _ nor /, then it's a whole
      else
      {
        numerator = Integer.parseInt(part);
        denominator = 1;
      }

      if (numerator != 0 && denominator != 0)
      {
        if (mode < 2)
        {
          if (denominator == allDenominators)
          {
            allNumerators += numerator;
          }
          else
          {
            // Cross multiply
            allNumerators *= denominator;

            if (mode == 0)
            {
              // Add
              allNumerators += numerator * allDenominators;
            }
            else
            {
              // Sub
              allNumerators -= numerator * allDenominators;
            }

            // Second part of cross multiply
            allDenominators *= denominator;
          }
        }
        // Multiplication
        else if (mode == 2)
        {
          allDenominators *= denominator;
          allNumerators *= numerator;
        }
        // Division
        else if (mode == 3)
        {
          // Reverse multiply because (1/2)/(1/2) -> (1*1)/(2*2)
          allNumerators = allNumerators * denominator;
          allDenominators = allDenominators * numerator;
        }

        // make sure denominators are +ve
        if (allDenominators < 0)
        {
          allNumerators = -allNumerators;
          allDenominators = -allDenominators;
        }
      }
    }

    // Simplifies fraction by checking to see id the top is bigger than bottom
    // 9/4 -> 2_1/4

    int allWholes = 0;
    if (allNumerators >= allDenominators)
    {
      allWholes = allNumerators / allDenominators;
      allNumerators %= allDenominators;
    }

    // consider implementing GCD to reduce num/den to simplest form

    if (allWholes == 0)
    {
      return (allNumerators + "/" + allDenominators);
    }
    else if (allNumerators == 0 || allDenominators == 0)
    {
      return allWholes + "";
    }
    else
    {
      return allWholes + "_" + (allNumerators + "/" + allDenominators);
    }
  }
}

输出:

-48/128
1_13/32

我认为这是正确的答案。顺便说一句,Symbolab有一个很棒的工具,可以让您输入包含分数的表达式,以便您检查结果。


推荐阅读