如何格式化小数精度

问题描述 投票:3回答:3

如何像下面给出格式化十进制数精度:

double d = 1/3返回0.3333333333333333和数学3被无限重复。

d = ((double)3)/ (double)41;返回0.07317073170731707这里07317是重复的。

现在,请格式化输出像下面

0.3333333333333333应格式化于0.(3)作为3被重复。

同样0.07317073170731707应该被格式化为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中的任何内置类可用来达到同样的?

java
3个回答
2
投票

正如在评论中指出,如果你只有一个String表示,首先,有没有办法判断实际上有一些重复的部分,它,如果精度根本不够高。

然而,从您的样品,看来你真的想找到你知道分子和分母为一个确切的整数分数的重复部分。这不是太难的问题;例如,你可以看看https://codereview.stackexchange.com/questions/87522/decimal-expansion-of-a-rational-number

===更新===

我正在表示与分子和分母作为BigIntegers有理数类(或假定为远减小为可能的)。在那里,我实现的方法产生的表示为十进制字符串并用以下想出了:

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

}

1
投票

不幸的是,我不知道这样一类的,也许数学家知道。问题是,一个无限的交涉一部分转向有限的,并且反复计算组必须象征性地进行,而不是用一些直接的二进制数。 (一个很好的学生项目可能。)

double是有缺陷的。人们可以做出基于BigDecimal可以识别循环小数,并存储这种“无限”的数字一个人的自己的类。像π许多无限号码仍然无法使用。

或者你可以创建(分子,分母)有理数类。

而对于一些罕见的情况下,你能避免受切换的基数,如整型/长可以与diferent基地工作,可以建立在该循环小数:

0.1 = 0.33333 ...基座3基座10


0
投票

你可以考虑到简单的重复,类似下面的方法。

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);
}
© www.soinside.com 2019 - 2024. All rights reserved.