Проблема:

У меня проблемы с вычислением целочисленного деления и отображением как Double (с плавающей запятой).

При меньших числах он отображается как с плавающей точкой, но кажется, что округляет значение до 11.0, 9.0, 28.0. После попытки решить проблему с помощью других сообщений StackO я не могу добиться того, чтобы она была последовательной. Благодаря некоторым решениям я смог отобразить его в виде решения с плавающей запятой, но при выполнении команд тестирования результаты не совпадают, когда они отображаются в виде плавающей запятой или нет.

Запрос на домашнее задание:

Напишите программу RandomWalkers.java, которая принимает два целочисленных аргумента командной строки 'r' и 'trials'. В каждом из испытаний независимых экспериментов моделируйте случайное блуждание, пока случайный бродяга не окажется на манхэттенском расстоянии r от начальной точки. Выведите среднее количество шагов.

По мере увеличения «r» мы ожидаем, что случайный бродяга будет делать все больше и больше шагов. Но сколько еще шагов? Используйте RandomWalkers.java, чтобы сформулировать гипотезу о том, как среднее число шагов растет как функция от «r».

Оценка неизвестного количества путем генерации случайных выборок и агрегирования результатов является примером моделирования Монте-Карло - мощной вычислительной техники, широко используемой в статистической физике, вычислительном финансировании и компьютерной графике.

Вы не можете вызывать библиотечные функции, кроме функций в java.lang (таких как Integer.parseInt() и Math.sqrt()). Используйте только те функции Java, которые уже были представлены в курсе (например, циклы и условные выражения, но не массивы ).

Что я пробовал:

  • Прочитайте по крайней мере 30+ различных страниц StackOverflow и других веб-сайтов о отображении целочисленного деления в виде числа с плавающей запятой (Double) и т. Д. И попробуйте все в них.

  • avgSteps = (double) totalNumSteps / trials;

  • изменение некоторых / всех переменных на Double

  • (totalNumSteps * 1.0) / trials;

  • (totalNumSteps + 0.0) / trials;

Иногда у меня есть прорыв, но потом я проверяю его немного больше, и он терпит неудачу с некоторыми или всеми аргументами, передаваемыми приложению.

Код:

Приведенный ниже код представляет собой очищенную базовую версию кода, за исключением любых тестов сверху.

public class RandomWalkers {

    public static void main(String[] args) {
        int r = Integer.parseInt(args[0]);
        int trials = Integer.parseInt(args[1]);
        int x = 0;
        int xx = 0;
        int y = 0;
        int yy = 0;
        int numSteps = 0;
        int totalNumSteps = 0;
        double randNum = 0.0;
        double avgSteps = 0.0;

        for (long i = 0; i < trials; i++) {
            while (Math.abs(x - xx) + Math.abs(y - yy) != r) {
                randNum = Math.random();
                if (randNum <= .25) {
                    // North
                    yy++;

                } else if (randNum <= .5) {
                    // East
                    xx++;

                } else if (randNum <= .75) {
                    // South
                    yy--;

                } else {
                    // West
                    xx--;

                }
                numSteps++;
            }
            totalNumSteps += numSteps;
        }

        avgSteps = totalNumSteps / trials;
        System.out.println("average number of steps = " + avgSteps);
    }

}

Ожидаемый результат:

Это запрошенные параметры и ожидаемый результат, предоставляемый в разделе «Домашнее задание».

~/Desktop/loops> java RandomWalkers 5 1000000

Среднее количество шагов = 14,98188

~/Desktop/loops> java RandomWalkers 5 1000000

Среднее количество шагов = 14,93918

~/Desktop/loops> java RandomWalkers 10 100000

Среднее количество шагов = 59,37386

~/Desktop/loops> java RandomWalkers 20 100000

Среднее количество шагов = 235,6288

~/Desktop/loops> java RandomWalkers 40 100000

Среднее количество шагов = 949,14712

~/Desktop/loops> java RandomWalkers 80 100000

Среднее количество шагов = 3775,7152

~/Desktop/loops> java RandomWalkers 160 100000

Среднее количество шагов = 15113,61108

Дипломная работа (фактический результат)

Проверка правильности RandomWalkers


Всего 7 тестов.

Тест 1: проверьте формат вывода

% java RandomWalkers 5 10000

Среднее количество шагов = 9,0

% java RandomWalkers 10 1000

Среднее количество шагов = 18,0

% java RandomWalkers 20 123456

Среднее количество шагов = 150,0

% java RandomWalkers 40 1

Среднее количество шагов = 726,0

% java RandomWalkers 1 10000

Среднее количество шагов = 1,0

% java RandomWalkers 0 333

Среднее количество шагов = 0,0

==> прошло

Тест 2: проверьте среднее количество шагов (испытаний = 10000) * java RandomWalkers 1 10000 * java RandomWalkers 2 10000 - среднее количество шагов у студента = 2,000000 - истинное среднее количество шагов = 2.6666666666666665 - 99,99% доверительный интервал = [2.617080, 2.716254] - правильное решение провалит этот тест по невезению примерно 1 раз в 10000

  • java RandomWalkers 3 10000

    • среднее число шагов для студента = 3.000000
    • истинное среднее количество шагов = 5,5709
    • доверительный интервал 99,99% = [5.443408, 5.698392]
    • правильное решение не пройдёт этот тест по невезению примерно 1 раз в 10000
  • java RandomWalkers 4 10000

    • среднее количество шагов у студента = 24,000000
    • истинное среднее количество шагов = 9,6808
    • доверительный интервал 99,99% = [9.444787, 9.916813]
    • правильное решение не пройдёт этот тест по невезению примерно 1 раз в 10000
  • java RandomWalkers 5 10000

    • среднее количество шагов у студента = 7,000000
    • истинное среднее количество шагов = 14,9775
    • доверительный интервал 99,99% = [14.602377, 15.352623]
    • правильное решение не пройдёт этот тест по невезению примерно 1 раз в 10000
  • java RandomWalkers 10 10000

    • среднее количество шагов у студента = 52,000000
    • истинное среднее количество шагов = 59,1465
    • доверительный интервал 99,99% = [57.612929, 60.680071]
    • правильное решение не пройдёт этот тест по невезению примерно 1 раз в 10000
  • java RandomWalkers 20 10000

    • среднее число шагов для студента = 390,000000
    • истинное среднее количество шагов = 235,9058
    • доверительный интервал 99,99% = [229.737686, 242.073914]
    • правильное решение не пройдёт этот тест по невезению примерно 1 раз в 10000
  • java RandomWalkers 40 10000

    • среднее число шагов для студента = 2056.000000
    • истинное среднее количество шагов = 943,3142
    • доверительный интервал 99,99% = [918.599036, 968.029364]
    • правильное решение не пройдёт этот тест по невезению примерно 1 раз в 10000

==> НЕ ПРОШЛО

Тест 3: проверьте среднее количество шагов (радиус = 5) * java RandomWalkers 5 100 - среднее количество шагов у студента = 11,000000 - истинное среднее количество шагов = 14,9775 - 99,99% доверительный интервал = [11.226273, 18.728727] - правильное решение провалит этот тест по невезению примерно 1 раз в 10000

  • java RandomWalkers 5 1000

    • среднее количество шагов у студента = 7,000000
    • истинное среднее количество шагов = 14,9775
    • доверительный интервал 99,99% = [13.791258, 16.163742]
    • правильное решение не пройдёт этот тест по невезению примерно 1 раз в 10000
  • java RandomWalkers 5 10000

    • среднее число шагов для студента = 5.000000
    • истинное среднее количество шагов = 14,9775
    • доверительный интервал 99,99% = [14.602377, 15.352623]
    • правильное решение не пройдёт этот тест по невезению примерно 1 раз в 10000
  • java RandomWalkers 5 100000

    • среднее число шагов для студента = 9,000000
    • истинное среднее количество шагов = 14,9775
    • доверительный интервал 99,99% = [14.858876, 15.096124]
    • правильное решение не пройдёт этот тест по невезению примерно 1 раз в 10000
  • java RandomWalkers 5 1000000

    • среднее количество шагов у студентов = 21,000000
    • истинное среднее количество шагов = 14,9775
    • доверительный интервал 99,99% = [14.939988, 15.015012]
    • правильное решение не пройдёт этот тест по невезению примерно 1 раз в 10000

==> НЕ ПРОШЛО

Тест 4: проверьте среднее количество шагов (радиус = 0) * java RandomWalkers 0 1000 * java RandomWalkers 0 100 * java RandomWalkers 0 1 ==> прошло

Тест 5: проверьте, что среднее число шагов не является целым числом * java RandomWalkers 10 1000 - среднее количество шагов у студента = 70,0 - правильное решение не пройдёт этот тест менее 1 раза из 10000

  • java RandomWalkers 7 2500

    • среднее число шагов для студента = 51,0
    • правильное решение не пройдёт этот тест менее 1 раза из 10000
  • java RandomWalkers 3 10000

    • среднее число шагов для студента = 5,0
    • правильное решение не пройдёт этот тест менее 1 раза из 10000

==> НЕ ПРОШЛО

Тест 6: убедитесь, что программа каждый раз дает разные результаты * java RandomWalkers 10 10000 [ repeated twice ] * java RandomWalkers 20 1000 [ repeated twice ] * java RandomWalkers 40 2000 [ repeated twice ] ==> прошло

Тест 7: проверьте случайность среднего количества шагов при испытаниях = 1 * java RandomWalkers 2 1 [ repeated 1024 times ] * java RandomWalkers 3 1 [ repeated 8192 times ] * java RandomWalkers 4 1 [ repeated 65536 times ] * java RandomWalkers 5 1 [ repeated 1048576 times ] ==> прошло

Всего RandomWalkers: 4/7 испытаний пройдено!

1
Arnaud A. 8 Май 2019 в 00:07

2 ответа

Лучший ответ

Итак, здесь было два вопроса. 1) Как отметил Карлос Хойбергер, вам необходимо каждый раз повторять инициализацию переменных в цикле. 2) Как вы заметили, нужно было позаботиться о том, чтобы деление было делением действительных чисел, а не оператором "div" для целых чисел. Я внес эти два изменения в ваш код (первые 5 строк в цикле for; (1.0 * испытания)), и он, похоже, прошел все тесты. Вы были близки

public class RandomWalkers {

public static void main(String[] args) {
    int r = Integer.parseInt(args[0]);
    int trials = Integer.parseInt(args[1]);
    int x = 0;
    int xx = 0;
    int y = 0;
    int yy = 0;
    int numSteps = 0;
    int totalNumSteps = 0;
    double randNum = 0.0;
    double avgSteps = 0.0;

    for (long i = 0; i < trials; i++) {
        x = 0;
        xx = 0;
        y = 0;
        yy = 0;
        numSteps = 0;
        while (Math.abs(x - xx) + Math.abs(y - yy) != r) {
            randNum = Math.random();
            if (randNum <= .25) {
                // North
                yy++;

            } else if (randNum <= .5) {
                // East
                xx++;

            } else if (randNum <= .75) {
                // South
                yy--;

            } else {
                // West
                xx--;

            }
            numSteps++;
        }
        totalNumSteps += numSteps;
    }

    avgSteps = totalNumSteps / (1.0 * trials);
    System.out.println("average number of steps = " + avgSteps);


   }

}
1
Jeremy Kahan 7 Май 2019 в 23:00

Подобные ошибки, как правило, случаются, когда переменные объявляются вне места назначения или использования.

Используя Java Microbenchmark Harness (JMH) Я не смог увидеть явных преимуществ в производительности между переназначением и повторным выделением переменных.

Однако я смог увидеть ОГРОМНОЕ (более чем в 2 раза быстрее) замены Math.Random на RANDOM.nextInt(4) и switch


import java.util.Random;

public class RandomWalkers {

    static final Random RANDOM = new Random();

    public static void main(final String[] args) {

        int r = Integer.parseInt(args[0]);

        int trials = Integer.parseInt(args[1]);

        int totalNumSteps = 0;

        for (long i = 0; i < trials; i++) {
            int x = 0;
            int xx = 0;
            int y = 0;
            int yy = 0;
            int numSteps = 0;

            while (Math.abs(x - xx) + Math.abs(y - yy) != r) {

                switch (RANDOM.nextInt(4)) {
                    case 0:
                        // North
                        yy++;
                        break;
                    case 1:
                        // East
                        xx++;
                        break;
                    case 2:
                        // South
                        yy--;
                        break;
                    default:
                        // West
                        xx--;
                }
                numSteps++;
            }

            totalNumSteps += numSteps;
        }

        double avgSteps = totalNumSteps / (1.0 * trials);
        System.out.println("average number of steps = " + avgSteps);
    }
}

Результаты P0,95 для r = 40

  • переназначить: 299,368 мс / оп
  • redeclareRandomIntSwitch: 139,107 мсек / операция

Мы можем сделать лучше

Явные if условия, хотя и немного менее читабельные, (в этом случае) быстрее, чем switch

Кроме того, поскольку мы работаем в однопоточном контексте, мы можем заменить java.util.Random на java.util.concurrent.ThreadLocalRandom.

Также явное приведение к double яснее, чем умножение на 1.0, и сохраняет нам два байт-кода.

Результаты P0,95 для r = 40

  • переназначить: 299,368 мс / оп
  • redeclareRandomIntSwitch: 139,107 мсек / операция
  • redeclareThreadLocalRandomIntIf: 122,539 мсек / операция

Код ниже почти в 2,5 раза быстрее.


package com.stackoverflow.q56030483;

import java.util.concurrent.ThreadLocalRandom;

@SuppressWarnings("javadoc")
public class RandomWalker {

    public static void main(final String[] args) {

        int r = Integer.parseInt(args[0]);

        int trials = Integer.parseInt(args[1]);

        int totalNumSteps = 0;

        final ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();

        for (long i = 0; i < trials; i++) {

            int x = 0;

            int xx = 0;

            int y = 0;

            int yy = 0;

            int numSteps = 0;

            while (Math.abs(x - xx) + Math.abs(y - yy) != r) {

                final int direction= threadLocalRandom.nextInt(4);

                // North
                if (direction == 0) {
                    yy++;

                // East
                } else if (direction == 1) {
                    xx++;

                // South
                } else if (direction == 2) {
                    yy--;

                // West
                } else {
                    xx--;
                }

                numSteps++;
            }

            totalNumSteps += numSteps;
        }

        System.out.println("average number of steps = " + totalNumSteps / (double) trials);

    }
}
Benchmark                                                                (arg)    Mode    Cnt    Score   Error  Units
RandomWalkers.reassign                                                       3  sample  37256    1.611 ± 0.002  ms/op
RandomWalkers.reassign:reassign·p0.00                                        3  sample           1.475          ms/op
RandomWalkers.reassign:reassign·p0.50                                        3  sample           1.593          ms/op
RandomWalkers.reassign:reassign·p0.90                                        3  sample           1.686          ms/op
RandomWalkers.reassign:reassign·p0.95                                        3  sample           1.780          ms/op
RandomWalkers.reassign:reassign·p0.99                                        3  sample           1.999          ms/op
RandomWalkers.reassign:reassign·p0.999                                       3  sample           2.507          ms/op
RandomWalkers.reassign:reassign·p0.9999                                      3  sample           4.367          ms/op
RandomWalkers.reassign:reassign·p1.00                                        3  sample          10.371          ms/op
RandomWalkers.reassign                                                      10  sample   3528   17.029 ± 0.063  ms/op
RandomWalkers.reassign:reassign·p0.00                                       10  sample          15.548          ms/op
RandomWalkers.reassign:reassign·p0.50                                       10  sample          16.712          ms/op
RandomWalkers.reassign:reassign·p0.90                                       10  sample          18.416          ms/op
RandomWalkers.reassign:reassign·p0.95                                       10  sample          18.842          ms/op
RandomWalkers.reassign:reassign·p0.99                                       10  sample          20.690          ms/op
RandomWalkers.reassign:reassign·p0.999                                      10  sample          27.636          ms/op
RandomWalkers.reassign:reassign·p0.9999                                     10  sample          36.176          ms/op
RandomWalkers.reassign:reassign·p1.00                                       10  sample          36.176          ms/op
RandomWalkers.reassign                                                      40  sample    227  268.714 ± 3.270  ms/op
RandomWalkers.reassign:reassign·p0.00                                       40  sample         251.134          ms/op
RandomWalkers.reassign:reassign·p0.50                                       40  sample         262.144          ms/op
RandomWalkers.reassign:reassign·p0.90                                       40  sample         296.223          ms/op
RandomWalkers.reassign:reassign·p0.95                                       40  sample         299.368          ms/op
RandomWalkers.reassign:reassign·p0.99                                       40  sample         303.416          ms/op
RandomWalkers.reassign:reassign·p0.999                                      40  sample         305.136          ms/op
RandomWalkers.reassign:reassign·p0.9999                                     40  sample         305.136          ms/op
RandomWalkers.reassign:reassign·p1.00                                       40  sample         305.136          ms/op
RandomWalkers.redeclareRandomIntSwitch                                       3  sample  69486    0.863 ± 0.001  ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.00        3  sample           0.763          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.50        3  sample           0.843          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.90        3  sample           0.925          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.95        3  sample           1.028          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.99        3  sample           1.155          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.999       3  sample           1.721          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.9999      3  sample           5.181          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p1.00        3  sample           9.355          ms/op
RandomWalkers.redeclareRandomIntSwitch                                      10  sample   7072    8.485 ± 0.040  ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.00       10  sample           7.668          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.50       10  sample           8.143          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.90       10  sample           9.650          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.95       10  sample          10.109          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.99       10  sample          11.960          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.999      10  sample          20.399          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.9999     10  sample          25.919          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p1.00       10  sample          25.919          ms/op
RandomWalkers.redeclareRandomIntSwitch                                      40  sample    466  130.302 ± 0.872  ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.00       40  sample         123.732          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.50       40  sample         128.844          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.90       40  sample         135.083          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.95       40  sample         139.107          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.99       40  sample         155.153          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.999      40  sample         182.452          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p0.9999     40  sample         182.452          ms/op
RandomWalkers.redeclareRandomIntSwitch:redeclareRandomIntSwitch·p1.00       40  sample         182.452          ms/op

RandomWalkers.redeclareThreadLocalRandomIntIf                                               40  sample   96  107.953 ± 2.148  ms/op
RandomWalkers.redeclareThreadLocalRandomIntIf:redeclareThreadLocalRandomIntIf·p0.00          40  sample        99.746          ms/op
RandomWalkers.redeclareThreadLocalRandomIntIf:redeclareThreadLocalRandomIntIf·p0.50          40  sample       107.676          ms/op
RandomWalkers.redeclareThreadLocalRandomIntIf:redeclareThreadLocalRandomIntIf·p0.90          40  sample       113.797          ms/op
RandomWalkers.redeclareThreadLocalRandomIntIf:redeclareThreadLocalRandomIntIf·p0.95          40  sample       122.539          ms/op
RandomWalkers.redeclareThreadLocalRandomIntIf:redeclareThreadLocalRandomIntIf·p0.99          40  sample       130.810          ms/op
RandomWalkers.redeclareThreadLocalRandomIntIf:redeclareThreadLocalRandomIntIf·p0.999         40  sample       130.810          ms/op
RandomWalkers.redeclareThreadLocalRandomIntIf:redeclareThreadLocalRandomIntIf·p0.9999     40  sample       130.810          ms/op
RandomWalkers.redeclareThreadLocalRandomIntIf:redeclareThreadLocalRandomIntIf·p1.00       40  sample       130.810          ms/op

0
Jeff 13 Май 2019 в 21:10