Проблема:
У меня проблемы с вычислением целочисленного деления и отображением как 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 испытаний пройдено!
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);
}
}
Подобные ошибки, как правило, случаются, когда переменные объявляются вне места назначения или использования.
Используя 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
Похожие вопросы
Новые вопросы
java
Java - это язык программирования высокого уровня. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег редко используется отдельно и чаще всего используется вместе с [spring], [spring-boot], [jakarta-ee], [android], [javafx], [hadoop], [gradle] и [maven].