代码之家  ›  专栏  ›  技术社区  ›  Shiva

如何设置十进制数精度的格式

  •  3
  • Shiva  · 技术社区  · 6 年前

    如何设置十进制数精度的格式,如下所示:

    double d = 1/3 返回 0.3333333333333333 数学上 3. 非常 .

    d = ((double)3)/ (double)41; 返回 0.07317073170731707 这里呢 07317

    现在,请求格式化输出,如下所示

    0.3333333333333333 应格式化为 0.(3) 重复第3步。

    同样地 应格式化为 0.(07317) 07317 重复的

    DecimalFormat 类,但我只能格式化精度的数量。

    public static void main(String[] args) {
            DecimalFormat formatter = new DecimalFormat("#0.'('##')'");
    
            double d = ((double)1)/ (double)3;
            System.out.println("formatted "+formatter.format(d));
            System.out.println(d);
    
    
            d = ((double)1)/ (double)2;
            System.out.println("formatted "+formatter.format(d));
            System.out.println(d);
    
    
            d = ((double)3)/ (double)41;
            System.out.println("formatted "+formatter.format(d));
            System.out.println(d);
    
        }
    

    输出:

    formatted 0.33()
    0.3333333333333333
    formatted 0.5()
    0.5
    formatted 0.07()
    0.07317073170731707
    

    JAVA 可以实现同样的效果吗?

    3 回复  |  直到 6 年前
        1
  •  2
  •   floxbr    6 年前

    正如注释中指出的,如果您只有一个字符串表示,那么首先,无法判断它是否确实有重复部分,或者精度是否不够高。

    然而,从您的示例中,似乎您实际上想要找到分数的重复部分,其中分子和分母都是精确整数。这不是一个太难的问题;例如,您可以查看 https://codereview.stackexchange.com/questions/87522/decimal-expansion-of-a-rational-number

    ==更新===

    我正在研究一个表示有理数的类,其分子和分母为大整数(并假设尽可能减少)。在那里,我实现了一个方法来生成十进制字符串表示形式,并得出以下结论:

    public String toDecimalString() {
    
        var result = new StringBuilder();
    
        var remainders = new HashMap<BigInteger, Integer>();
    
        if(!isNonNegative()) result.append("-");
        var divAndRem = numerator.abs().divideAndRemainder(denominator);
        result.append(divAndRem[0].toString());
    
        if(isWholeNumber()) return result.toString();
    
        result.append(".");
    
        int currentPosition = result.length();
        remainders.put(divAndRem[1], currentPosition);
    
        while(!divAndRem[1].equals(BigInteger.ZERO)) {
            divAndRem = divAndRem[1].multiply(BigInteger.TEN).divideAndRemainder(denominator);
            result.append(divAndRem[0].toString());
            if(remainders.containsKey(divAndRem[1])) {
                int periodStart = remainders.get(divAndRem[1]);
                return result.substring(0, periodStart)+"["+result.substring(periodStart)+"]";
            }
            remainders.put(divAndRem[1], ++currentPosition);
        }
    
        return result.toString();
    
    }
    
        2
  •  1
  •   Joop Eggen    6 年前

    (也许是个不错的学生项目。)

    double 这是有缺陷的。一个人可以根据自己的喜好来制作自己的课程 BigDecimal 它可以识别重复的小数,并存储这样的“无限”数字。许多无穷多的数字像 π 仍然无法使用。

    或者您可以使用(分子、分母)创建一个有理数类。

    对于一些罕见的情况,你可以通过切换基数来避免重复小数,

    0.1基数3=0.33333。。。基数10

        3
  •  0
  •   MIR    6 年前

    您可以创建一个考虑简单重复的方法,如下所示。

    public static double reformatNumber(double number) {
      String s = String.valueOf(number);
    
      String[] split = s.split("\\.");
    
      String result = split[1].substring(0,8); // Length to consider
      String actualDigit = "";
      String lastDigit = "";
      int counter = 0;
      for (int i = 1; i <= result.length(); i++) {
        actualDigit = result.substring(i-1,i);
        if (actualDigit.equals(lastDigit)) {
          counter++;
        } else {
          counter = 0;
        }
        lastDigit = actualDigit;
        if (counter == 3) { // Number of repetitions in a row required
          result = result.substring(0,i-1);
        }
      }
      s = split[0]+"."+result;
    
      return Double.parseDouble(s);
    }
    

    如果你想考虑两个或多个重复,只需修改最后一个方法来保存两个数字一次,像这样。

    public static double reformatNumber(double number) {
      String s = String.valueOf(number);
    
      String[] split = s.split("\\.");
    
      String result = split[1].substring(0,8);
      String actualDigit = "";
      String lastDigit = "";
      int counter = 0;
      for (int i = 1; i <= result.length(); i++) {
        actualDigit = result.substring(i-1,i);
        if (actualDigit.equals(lastDigit)) {
          counter++;
        } else if (i%4 == 0 && (actualDigit+lastDigit).equals(result.substring(i-4,i-2))) { 
          // Every four cycles checks if the last digit and the current one 
          // are equals to the last two digits before the last digit
          counter++;
        } else {
          counter = 0;
        }
        lastDigit = actualDigit;
        if (counter == 3) {
          result = result.substring(0,i-1);
          break;
        }
      }
      s = split[0]+"."+result;
    
      return Double.parseDouble(s);
    }