Java 确保十进制数的字符串长度始终为n个字符

Java 确保十进制数的字符串长度始终为n个字符,java,string-formatting,number-formatting,decimalformat,Java,String Formatting,Number Formatting,Decimalformat,我需要确保我所有的十进制数总是最多15个字符(包括点),同时保持尽可能高的精度。因此,它最多必须是15个字符,包括“.”表示科学记数法的“E”和“-” 我的想法是对大数字使用科学记数法,对小数字使用舍入法 例如,对于1234567891234567.123456789,我会使用科学记数法,但是对于0.123456789123456789,我会将其四舍五入 我寻找了可以为我实现这一点的java库,但找不到任何可以让我指定表示的字符总数的库 感谢您的建议和指点 编辑:更多想法-使用24000E-18

我需要确保我所有的十进制数总是最多15个字符(包括点),同时保持尽可能高的精度。因此,它最多必须是15个字符,包括“.”表示科学记数法的“E”和“-”

我的想法是对大数字使用科学记数法,对小数字使用舍入法

例如,对于1234567891234567.123456789,我会使用科学记数法,但是对于0.123456789123456789,我会将其四舍五入

我寻找了可以为我实现这一点的java库,但找不到任何可以让我指定表示的字符总数的库

感谢您的建议和指点

编辑:更多想法-使用24000E-18可以毫无损失地表示0.000000000000024等数字。例如,0.123456789123424必须遭受一些损失,这当然会使编写任何类型的简单分支算法变得更加困难

EDIT2:我们用于传输数据的格式是字母数字格式,并且将数据限制为总共15个字符。我必须编写满足格式要求的代码,以便在不触发格式错误的情况下传输数据,但同时仍将最大精度保持在限制范围内

EDIT3:我用它来测试我的功能,但到目前为止,在很多情况下,一切都失败了:

  Random rnd = new Random();
  double n = 100000 + rnd.nextDouble() * 900000;
  String res;
  double rangeMin = -123456789123456D;
  double rangeMax = 123456789123456D;
  String val;
  for (int i=1;i<=1000;i++) {
    n = rangeMin + (rangeMax - rangeMin) * rnd.nextDouble();
    val = Double.toString(n);
    res = shorteningFunction(val);
    System.out.println(val + " " + val.length() + " " + res + " " + res.length());
  }
Random rnd=new Random();
双n=100000+rnd.nextDouble()*900000;
字符串res;
双量程最小值=-123456789123456D;
双量程最大值=123456789123456D;
字符串val;

对于(inti=1;i我不希望发布不起作用的代码,所以我已经删除了混乱

这就是伪代码中的想法:

  • 把它变成一根绳子
  • 检查长度
  • 循环:
    • 如果长度太长:
    • 除去预感
    • 把它变成一根绳子
    • 检查长度
  • 返回

  • 可以使用
    BigDecimal
    ,对于整数部分
    biginger

    /**
     * @param num number representation.
     * @param max the maximal length the result should have.
     * @return
     */
    public static String truncateNumber(String num, int max) {
        num = num.replaceFirst("\\.0*$", "");
        BigDecimal x = new BigDecimal(num);
    
        // Large numbers - integral part
        String bigI = x.toBigInteger().toString();
        if (bigI.length() > max) {
            int expon10 = bigI.length() - max - 1; // - 1 for E
    
            // Digits after E:
            if (expon10 == 0) {
                ++expon10;
            } else {
                for (int p = expon10; p > 0; ++p) {
                    ++expon10;
                    p /= 10;
                }
            }
            x = x.movePointLeft(expon10);
            String plain = x.toPlainString().substring(0, max - 1 - expon10);
            return plain + "E" + expon10;
        }
    
        // Tiny numbers - 0.000 (as E-1 already requires 3 positions)
        String reprP = x.toPlainString();
        if (reprP.startsWith("-0.00")) {
            return truncateNumber(num.substring(1), max - 1);
        } else if (reprP.startsWith("0.00")) {
            String reprE = x.toEngineeringString(); // Does most work.
            int epos = reprE.indexOf('E');
            String mantissa = reprE.substring(0, epos);
            String exp = reprE.substring(epos);
            return mantissa.substring(0, Math.min(epos, max - exp.length())) + exp;
        }
    
        // Normal range - assumed in format 123.456, integral part in range
        String simple = x.toPlainString();
        if (simple.length() > max) {
            simple = simple.substring(0, max).replaceFirst("\\.0*$", "");
        }
        return simple;
    }
    
    这可能会写得更好,子字符串以
    \.0*
    结尾,尤其是toPlainString之类的重复使用。此外,过小的
    max
    也会有害


    是否用科学/工程符号给出
    num
    也是开放的。

    您应该使用
    BigDecimal
    ,然后设置您想要的精度。@TimBiegeleisen精度似乎不处理字符,而是处理数字。也许我缺少它,但我不知道如何限制字符总数?可以吗你介意重新开始我的问题吗?这似乎不能回答问题?一个数字不是一个字符吗?@TimBiegeleisen确实是,但它不包括点字符或“E”当使用科学记数法时。有这个要求是没有意义的。这难道不是意味着不是所有的数字都会以相同的精度存储吗?你真的想要吗?回答得很好,但是
    -1234567889123456
    会导致
    -1.2345678912346E+14
    (长度20).这确实是一个很好的起点,谢谢!0.00542299没有任何变化(16个字符).我在刚刚编辑的内容中提供了一个测试功能。@delica我有一个问题。通常情况下,什么让答案被接受?通常情况下,什么让答案被标记为有用?我会说,如果它起作用,那么它就被接受为答案。如果它不起作用,那么接受它就没有意义,因为其他人会认为它已经解决了,不会发布更多的答案。This运行得很好,只是它通常会缩短太多:5.273913272867031E12->5273913272867(例如,从20到13个字符)。@delica很高兴知道,但我把精确解留给你来解决。特别是当你深入了解问题时。祝你好运谢谢你的部分解决方案!谢谢!