Java中是否有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

在将算法从JavaScript移植到Java的过程中,我遇到了一个问题,即需要替换JavaScript的toPrecision()。问题是,我不知道这些数字会有多小或多大,所以我不能使用具有正确格式的简单数字格式

是否有提供类似功能的标准类

编辑 以下是我的想法:

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