Убедиться, что длина строки десятичного числа всегда равна n символов - PullRequest
3 голосов
/ 10 января 2020

Мне нужно убедиться, что все мои десятичные числа всегда имеют длину не более 15 символов (включая точку), сохраняя при этом как можно большую точность. Таким образом, это должно быть максимум 15 символов, включая «.» «E» для обозначения scientifi c и «-».

Я думал о том, чтобы использовать обозначение scientifi c для больших чисел и использовать округление для небольших чисел.

Например, для 1234567891234567.123456789 я бы использовал scientifi c нотацию, но для 0.123456789123456789 я бы просто округлил ее. Я могу указать общее количество символов для представления.

Благодарен за любые предложения или указатели.

РЕДАКТИРОВАТЬ: еще несколько мыслей - число, такое как 0,000000000000024, можно представить без потерь с помощью 24000E -18. В то время как 0.123456789123424, например, должен понести некоторые потери, что, конечно, затрудняет написание каких-либо простых ветвлений al go.

EDIT2: формат, который мы используем для передачи данных, это альфа-цифра 1022 * и ограничивает данные до 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());
  }

Ответы [ 2 ]

1 голос
/ 16 января 2020

Можно использовать BigDecimal, а для целочисленной части BigInteger.

/**
 * @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 быть дан в научной науке c / также открыта инженерная запись.

1 голос
/ 14 января 2020

Я не хотел, чтобы опубликованный код не работал, поэтому я удалил беспорядок.

Это идея в псевдокоде:

  1. Преврати его в строку.
  2. Проверьте длину
  3. L oop:
    • Если длина слишком велика:
    • Снимите предписание.
    • Поверните его в строку.
    • Проверьте длину.
  4. Возврат
...