#java
#java
Вопрос:
Когда я запускаю следующий код в Intellij с вводом 1000000000000, процесс задерживается на мгновение каждые 8 миллионов циклов.
Почему это так? Почему не выполняется в одном плавном потоке до конца?
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("Please type a number");
long n = in.nextLong();
System.out.println("Thanks.");
long count = 0;
for (long i=0; i<=n; i ) {
if ((n i) == (n^i)) {
count ;
if (count % 1000000 == 0)
System.out.println(count);
}
}
System.out.println(count);
}
}
Комментарии:
1. Как вы определили «паузу»?
2. Просто смотрю на стандартный вывод. Он останавливается каждые 8 миллионов итераций.
3. @RichArt это не «останавливается» каждые 8 миллионов итераций. Он все еще работает. Просто вы печатаете что — то только раз в миллион раз больше
(n i) == (n^i)
.4. Да, но дело в том, что он печатает до 8 миллионов, а затем останавливается, затем снова печатает до 16 миллионов и снова останавливается, и так далее.
5. @AndyTurner Я полагаю, что он это понимает. У меня сложилось впечатление, что он говорит, что каждое восьмое печатное заявление, кажется, занимает больше времени, чем предыдущие 7.
Ответ №1:
Условие
(n i) == (n ^ i)
будет происходить в основном, когда в and нет перекрывающихся битов n
i
, поскольку в этом случае сложение и XOR — это, по сути, одно и то же.
Например, если n == 4
и i == 3
, то в двоичном n == 100
и i == 011
, так
n i == 100 011 == 111 == 7
n ^ i == 100 ^ 011 == 111 == 7
Я не уверен, что нет чисел с общими битами, для которых также выполняется условие; но это «очевидные» случаи, для которых это верно.
Двоичная форма 1000000000000 равна
1110100011010100101001010001000000000000
Наименее значимым установленным битом здесь является 12-й бит (начиная с нулевого справа).
12-я степень 2 равна 4096. Итак, все числа меньше 4096 не имеют общих битов с n
, поэтому вы будете считать все числа 0-4095. С этого момента вы будете считать только те числа, для которых не установлен 12-й бит. Таким образом, скорость подсчета чисел будет замедляться.
Затем вы попадете на 16-й LSB. Теперь вы будете считать только числа без набора 12-го и 16-го битов. Таким образом, скорость подсчета чисел еще немного замедлится.
и т.д. и т.п.
Единственная причина этих «пауз» заключается в том, что внешний цикл for наивно перебирает все числа вплоть до n
: он не просто переходит к следующему числу, для которого выполняется условие.
Комментарии:
1. И вы можете увидеть, что это действительно так, запустив программу с вводом, скажем, 1048576, который равен 1 << 20 и, следовательно, имеет все младшие биты равными нулю.
2. @Andy: вы написали: «Я не уверен, что нет чисел с общими битами, для которых также выполняется условие». Можете ли вы привести пример? Я не могу понять, что вы имеете в виду.
3. @RichArt если бы я мог привести пример, я был бы убежден, что такой пример существует! Возможно, этого не может быть; Я просто не хочу этого утверждать, потому что я не склонен это доказывать.
4. @RichArt Нет, время вычисления выражения здесь не оказывает существенного влияния. Просто есть все более и более длинные «пробелы», где ничего не печатается, потому что выражение вычисляется
false
.5. @RichArt да, это так просто.