Java сумма повторяющихся элементов внутри цикла for - PullRequest
0 голосов
/ 30 мая 2020

У меня есть два массива:

String[] matnr = new String[] { "16400", "56000", "56000", "50000", "16400" };
String[] lfimg = new String[] { "4.000", "5.000", "6.000", "9.000", "10.560" };

Я хочу найти сумму элементов lfimg, имеющих одинаковое значение matnr, т.е. для matnr 16400 сумма вывода будет 14.560, для 56000 вывод будет 11.000 и matnr 50000 сумма вывода будет 9.000

ниже блок написан мной:

    public static void main(String[] args) {

        String[] matnr = new String[] { "16400", "56000", "56000", "50000", "16400" };
        String[] lfimg = new String[] { "4.000", "5.000", "6.000", "9.000", "10.56" };

        int n = matnr.length;

        int i, j, x;
        int count = 0;
        int count1 = 0;
        double value = 0.0;

        // calculate unique material count
        for (i = 0; i < n; ++i)
            System.out.println(i + 1 + "compartment material : " + matnr[i]);

        for (i = 0; i < n; i++) {
            for (j = 0; j < i; j++)
                if (matnr[i] == matnr[j])
                    break;
            if (i == j) {
                count = count + 1;
            }

        }
        System.out.println("final count >>" + count);
        String materialArray[] = new String[count];

        for (i = 0; i < n; i++) {
            for (j = 0; j < i; j++)
                if (matnr[i] == matnr[j])
                    break;
            if (i == j) {

                materialArray[count1] = matnr[i];
                System.out.println("Material array xxxx >>" + materialArray[count1]);
                System.out.println("count1 before >>" + count1);
                count1 = count1 + 1;
                System.out.println("count1 after >>" + count1);

            }

        }

        System.out.println("matnr.length >>" + matnr.length);
        System.out.println("materialArray.length >>" + materialArray.length);

        for (i = 0; i < matnr.length; i++) {
            System.out.println("111Value   >>> " + matnr[i]);
        }

        for (j = 0; j < materialArray.length; j++) {
            System.out.println("222Value >>> " + materialArray[j]);
        }

        System.out.println("---- ******* ------------ *********** -------- ********** ------");

        for (i = 0; i < materialArray.length; i++) {
            for (j = 0; j < matnr.length; j++) {
                if (materialArray[i].contains(matnr[j])) {

                    value = value + Double.parseDouble(lfimg[j]);

                    System.out.println("Value1   >>>  " + value);

                }

            }

        }

    }

Но я не получаю желаемого результата. Он выглядит так:

Value1   >>>  4.0
Value1   >>>  14.56
Value1   >>>  19.560000000000002
Value1   >>>  25.560000000000002
Value1   >>>  34.56

Где, как я хочу, выводится как:

Value1   >>>  14.560
Value1   >>>  11.000
Value1   >>>  9.000

Кто-нибудь может помочь в этом отношении.

1 Ответ

3 голосов
/ 30 мая 2020
  1. Вы не сбрасываете переменную value в своем окончательном forl oop, поэтому вы получаете постоянно увеличивающиеся числа в вашей печати, заканчивающиеся на 34.56. Вам нужно одно значение для каждой записи materialArray, поэтому сразу после for (i = 0; i < materialArray.length; i++) { вам нужно будет value = 0.
  2. Вы используете materialArray[i].contains(matnr[j]) - это спрашивает, является ли matnr [j] подстрокой materialArray [я]. Кажется довольно очевидным, что вы хотели вместо этого equals. Незначительная нить и здесь не ломается, но, тем не менее, это ошибка.
  3. Ваш принтер будет печатать каждый раз, когда индивидуальная запись совпадает, и ничего не печатает после того, как вы пройдете весь список, что приведет к этому странному выводу . Предположительно ваше намерение состоит в том, чтобы позволить внутреннему l oop (for (int j = 0; j < matnr.length; j++)) завершиться, а ЗАТЕМ вы хотите распечатать. Таким образом, ваш оператор sysout должен быть сдвинут на две строки вниз, после закрывающей скобки внутреннего для l oop. Совместите это со сбросом value и ...
Value1   >>>  14.56
Value1   >>>  11.0
Value1   >>>  9.0

NB: Вторая проблема - это ошибки округления. Вы в основном должны никогда toString () или иным образом напрямую печатать значение с плавающей запятой или двойное значение. Если вы это сделаете, вы получите шаткую странность, например, 19.560000000000002.

Если я попрошу вас, используя десятичную запись, записать результат «одна треть», вы должны округлить. Вы не можете написать бесконечную обработку 0,33333333, верно? Компьютеры (в частности, double и float) ничем не отличаются, но компьютеры считают двоичными, а не десятичными. Итак, компьютер должен немного округлить, а затем «визуализировать» имеющееся значение в десятичном формате, и отсюда возникает странность. Неточностей, вносимых этим округлением, невозможно избежать (по крайней мере, не с помощью удвоений и чисел с плавающей запятой), но обычно неточности не вкрадываются в соответствующее значение ваших чисел. Поэтому решение - ВСЕГДА направлять библиотеки при печати ваших чисел, сообщая им, сколько цифр вы ожидаете. Итак, сделайте это:

System.out.printf("Value1   >>>   %.4f\n", value);

%.4f сообщает принтеру печатать с не более чем 4 цифрами после точки, а printf не переводит автоматически новую строку, поэтому \n сообщает ему напечатайте эту новую строку явно.

Наконец, это вопрос этого стиля кода. Это можно сделать гораздо проще (и эффективнее) с помощью встроенных инструментов java, таких как HashMap:

    public static void main(String[] args) {
        String[] matnr = new String[] { "16400", "56000", "56000", "50000", "16400" };
        String[] lfimg = new String[] { "4.000", "5.000", "6.000", "9.000", "10.56" };
        var values = new HashMap<String, Double>();

        // load values into the map.
        for (int i = 0; i < matnr.length; i++) {
            double z = Double.parseDouble(lfimg[i]);
            values.compute(matnr[i], (m, v) -> v == null ? z : v + z); // [1]
        }

        // print them to show it works
        for (var e : values.entrySet()) {
            System.out.printf("%s: %.4f\n", e.getKey(), e.getValue());
        }
    }

Ключевая строка - это строка с пометкой [1]: в ней говорится: Чтобы вычислить значение для значения в текущей записи matnr, если еще нет существующего значения (v будет нулевым), это просто соответствующая запись из lfimg, а если есть существующее значение, это сумма того, что у нас было, плюс соответствующая запись из lfimg.

...