Java中是否有toPrecision()的等价物?
在将算法从JavaScript移植到Java的过程中,我遇到了一个问题,即需要替换JavaScript的toPrecision()。问题是,我不知道这些数字会有多小或多大,所以我不能使用具有正确格式的简单数字格式 是否有提供类似功能的标准类 编辑 以下是我的想法:Java中是否有toPrecision()的等价物?,java,Java,在将算法从JavaScript移植到Java的过程中,我遇到了一个问题,即需要替换JavaScript的toPrecision()。问题是,我不知道这些数字会有多小或多大,所以我不能使用具有正确格式的简单数字格式 是否有提供类似功能的标准类 编辑 以下是我的想法: double toPrecision(double n, double p) { if (n==0) return 0; double e = Math.floor(Math.log10(Mat
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.2999999997
编辑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;
}
双精度(双n,双p){
如果(n==0)返回0;
double e=Math.floor(Math.log10(Math.abs(n));
double f=Math.round(Math.exp((Math.abs(e-p+1))*Math.log(10));
如果(e-p+1使用和方法设置精度
BigDecimal bd = new BigDecimal("1.23456789");
System.out.println(bd.setScale(3,BigDecimal.ROUND_HALF_UP));
输出
1.235
看
您可以使用
double d = 1.23456789;
System.out.println(Math.round(d * 1e3) / 1e3);
印刷品
1.235
1.23E7
1.23E-6
或
同样的道理
您可以使用NumberFormat仅显示为十进制
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));
}
}
.##表示您想要的小数位数
我希望这能满足您的要求。这终于起作用了
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;
}
双精度(双n,双p){
如果(n==0)返回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我为此提出的最简单的解决方案使用了java.math.BigDecimal
和java.math.MathContext
的组合
String toPrecision(double number, int precision) {
return new BigDecimal(number, new MathContext(precision)).toString();
}
我在of中使用它。这是一个使用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;
}
.replace仅在您想要模拟javascript时才需要,因为它在指数上没有前导零
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);
}
不符合我的要求。我事先不知道数字的刻度,因此在一种情况下,输入可能是12345678.9,应该返回12300000;在另一种情况下,0.00000012345应该返回000000123。还有舍入问题,请参阅我编辑的帖子。@ammoQ我给出的代码没有舍入问题,并且给出了与Jigar相同的答案s.将修改为处理N个有效数字。不完全是,请参阅我对Peter答案的评论。在您的解决方案中,找不到正确的刻度,但使用BigDecimal似乎是个好主意。它不显示三个有效数字,例如“12345678.9,应返回12300000”@Erichkizmueller这是错误的解决方案。尝试以下方法:输入0.0000001以获得精度(3)您的代码给出的答案为0.000,而Javascript给出的答案为1.00e-7,即0.0000001,以使其完全模仿Javascript行为(特别是对于科学记数法),我们必须将结果转换为小写。这实际上适用于输入404279.164
和4
==404300.0
,这正是我想要的。inline fun Double.toPrecision(s:Int)=bigdecimic(This,MathContext(s)).toDouble()
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);
}