如何格式化小数位数精度,如下所示:
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 中是否有任何内置类可以实现相同目的?
答案 0 :(得分: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 :(得分:1)
不幸的是,我不知道这样的一类,也许数学家知道。问题在于无限表示的一部分变成了有限表示,并且必须用符号进行重复组的计算,而不是使用一些立即二进制数。 (也许是一个不错的学生项目。)
double
有缺陷。一个人可以基于BigDecimal
来创建自己的类,该类可以标识重复的小数并存储这样的“无限”数字。像π这样的许多无穷数仍然无法使用。
或者您可以使用(分子,分母)创建有理数类。
在极少数情况下,您可以通过切换数字基数来避免重复小数, 因为Integer / Long可以使用不同的基础,并且可以在此基础上构建:
0.1以3为基= 0.33333 ...以10为基
答案 2 :(得分: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);
}