在将算法从JavaScript移植到Java时,我遇到了需要替换JavaScript的toPrecision()的问题。问题是我不知道数字的大小有多大,所以我不能使用格式正确的NumberFormat。
是否有提供类似功能的标准类?
EDIT 以下是我提出的建议:
double toPrecision(double n, double p) {
if (n==0) return 0;
double e = Math.floor(Math.log10(Math.abs(n)));
double f = Math.exp((e-p+1)*Math.log(10));
return Math.round(n/f)*f;
}
原则上,它做了正确的事情,但舍入错误完全毁了它。例如,
toPrecision(12.34567, 3)
返回12.299999999999997
编辑2 这个版本适用于12个测试用例中的11个......
double toPrecision(double n, double p) {
if (n==0) return 0;
double e = Math.floor(Math.log10(Math.abs(n)));
double f = Math.round(Math.exp((Math.abs(e-p+1))*Math.log(10)));
if (e-p+1<0) {
f = 1/f;
}
return Math.round(n/f)*f;
}
但toPrecision(0.00001234567, 3)
仍然会返回1.2299999999999999E-5
而不是1.23E-5
答案 0 :(得分:12)
使用BigDecimal
和setScale()
方法设置精度
BigDecimal bd = new BigDecimal("1.23456789");
System.out.println(bd.setScale(3,BigDecimal.ROUND_HALF_UP));
<强>输出强>
1.235
见
答案 1 :(得分:3)
我提出的最简单的解决方案是使用java.math.BigDecimal
和java.math.MathContext
的组合。
String toPrecision(double number, int precision) {
return new BigDecimal(number, new MathContext(precision)).toString();
}
答案 2 :(得分:2)
这是一个使用String.format的java解决方案。
public static String toPrecision(double d, int digits) {
s = String.format("%."+((digits>0)?digits:16)+"g",d).replace("e+0","e+").replace("e-0","e-");
return s;
}
只有在你想要模仿javascript的时候才需要.replace,它在exponents上没有前导零。如果您只是将其用于舍入,则将值返回为
return Double.parseDouble(s);
以下是一些单元测试代码:
public void testToPrecision() {
String s = NumberFormat.toPrecision(1234567.0,5);
assertEquals("1.2346e+6",s);
s = NumberFormat.toPrecision(12.34567,5);
assertEquals("12.346",s);
s = NumberFormat.toPrecision(0.1234567,5);
assertEquals("0.12346",s);
s = NumberFormat.toPrecision(0.1234567e20,5);
assertEquals("1.2346e+19",s);
s = NumberFormat.toPrecision(-0.1234567e-8,5);
assertEquals("-1.2346e-9",s);
s = NumberFormat.toPrecision(1.0/3.0,5);
assertEquals("0.33333",s);
s = NumberFormat.toPrecision(1.0/3.0,0);
assertEquals("0.3333333333333333",s);
}
答案 3 :(得分:1)
您可以将double
与
double d = 1.23456789;
System.out.println(Math.round(d * 1e3) / 1e3);
打印
1.235
或
System.out.printf("%.3f%n", d);
也一样。
public static void main(String... args) {
System.out.println(round3significant(12345678.9));
System.out.println(round3significant(0.0000012345));
}
public static double round3significant(double d) {
if (d < 100) {
double divide = 1;
while(d < 100) {
d *= 10;
divide *= 10;
}
return Math.round(d) / divide;
} else {
double multi = 1;
while(d > 1000) {
d /= 10;
multi *= 10;
}
return Math.round(d) * multi;
}
}
打印
1.23E7
1.23E-6
您可以使用NumberFormat仅显示为小数。
答案 4 :(得分:1)
这最终有效......
double toPrecision(double n, double p) {
if (n==0) return 0;
double e = Math.floor(Math.log10(Math.abs(n)));
double f = Math.round(Math.exp((Math.abs(e-p+1))*Math.log(10)));
if (e-p+1<0) {
return Math.round(n*f)/f;
}
return Math.round(n/f)*f;
}
答案 5 :(得分:0)
import java.text.*;
Class Decimals
{
public static void main(String[] args)
{
float f = 125.069f;
DecimalFormat form = new DecimalFormat("#.##");
System.out.println(form.format(f));
}
}
。##代表你想要的小数位数 我希望这符合你的要求。