Подтвердить что ты не робот

Как сравнить два значения времени nano? [javadoc confusion]

Я прочитал javadoc для System.nanoTime(), и все это кажется ясным. Пока я не дошел до финального абзаца:

Чтобы сравнить два значения nanoTime

long t0 = System.nanoTime();

...

long t1 = System.nanoTime();

следует использовать t1 - t0 < 0, а не t1 < t0, из-за возможности численного переполнения.

Есть две вещи, которые мне непонятно:

  • Почему бы проверить, если t1 < t0, если t1 было взято после t0? Я понимаю, что нано-время всегда увеличивается. Итак, я бы предпочел проверить t1 > t0.
  • Предположим, что опечатка, и они означали правильную проверку t1 - t0 > 0. Я до сих пор не понимаю, почему это правильный способ проверки, а не t1 > t0. Они упоминают численное переполнение, и я не совсем понимаю, что они означают. Что касается численного переполнения, здесь упоминается следующее:

Различия в последовательных вызовах, которые охватывают более 292 лет (2 ^ 63 наносекунды), не будут правильно вычислять прошедшее время из-за численного переполнения.

ОК, поэтому, поскольку нано-время хранится как длинное значение, оно в конечном итоге переполняется через 292 года. И что будет дальше? Началось ли это с самого начала, т.е. Самое низкое отрицательное значение -2 ^ 63? Или он всегда останавливает измерение и возвращает (2 ^ 63 - 1)?

4b9b3361

Ответ 1

Вы правы, части документации, которые вы цитировали, немного запутались.

Однако часть документации, которая имеет значение, такова:

Этот метод может использоваться только для измерения прошедшего времени и не имеет отношения к какому-либо другому понятию системного или настенного времени. Возвращаемое значение представляет собой наносекунды с некоторого фиксированного, но произвольного времени начала (возможно, в будущем, поэтому значения могут быть отрицательными). Такое же происхождение используется всеми вызовами этого метода в экземпляре виртуальной машины Java; другие экземпляры виртуальной машины могут использовать другое происхождение.

(выделено мной мной.)

Это означает, что у вас нет никаких гарантий того, что ваш код не будет работать в то время, когда полученное длинное значение произойдет с переводом с положительного на отрицательный.

Нет ничего, что гарантировало бы, что это произойдет через 300 лет, это может произойти сегодня.

В настоящее время моя JVM возвращает некоторое число, например 3496793269188, но если бы оно захотелось, было бы возвращено некоторое число, очень близкое к 9223372036854775807 (это Long.MAX_VALUE), которое сделало бы переворот с положительного на отрицательный.

Итак, вы должны принять все необходимые меры предосторожности.

Ответ 2

Ну, javadoc говорит правду. Рассмотрим такой пример:

        long t0 = Long.MAX_VALUE;
        long t1 = Long.MIN_VALUE;

        System.out.println(t1 < t0);
        System.out.println(t1 - t0 < 0);

Он даст

true
false

тогда как математически оба выражения истинны. Но в нашем случае мы знаем, что отрицательное значение time означает, что оно переполнено, следовательно, оно должно быть действительно большим, чем положительное число.

Ответ 3

Позвольте мне начать с конца вашего вопроса. Да в случае, если значение больше 2 ^ 63-1, значение будет переполняться. Общая реализация переполнения заключается в том, что сохраняются наименее значимые представляемые биты результата; значение будет wrap (вы можете увидеть в нижней части моего сообщения о переполнении для справки)

Последовательность: 2^63-2, 2^63-1, -2^63, -(2^63-1) ...

Теперь, оглядываясь назад на Javadoc, я согласен с тем, что объяснение использования сравнения путается, и, естественно, мы попытаемся сравнить t1 > t0, чтобы проверить, произошло ли t1 после t0. Вы частично правы. Хотя я не думаю, что это опечатка, но она не объясняется правильно. Я думаю, он должен сказать:

Для двух значений t0 и t1 (где t1 захватывается после t0), вы не должны использовать t1 < t0 (для проверки false), а скорее t1 - t0 < 0, аналогично вам не следует использовать t1 > t0 (для проверки true), но скорее t1 - t0 > 0

Или для его формализации:

Для двух значений "nano" t0 и t1, где t1 захватывается после t0 следующих таблиц: (t1 - t0 > 0) == true, пока период между t1 и t0 составляет <= 2 ^ 63 нс.

Почему? Поскольку даже когда t1 переполняется (поэтому он отрицательный), результат t1 - t0 также будет отрицательным , но он будет меньше -2 ^ 64, и он будет "переполняться назад" до положительного значения!.

Это стоит, пока выполняется условие о расстоянии между t0 и t1! В случае, если расстояние больше 2 ^ 64, например: для t0 = 1; t1 = -(2^64-2), результат вычитания будет: t1 - t0 = -(2^64-1), поэтому указанное условие (t1 - t0 > 0) даст неверный результат.

Right:)

При переполнении

Для объяснения lats принимает тип, который хранится с использованием 8 бит (вместо 64 используется длинным), поэтому двоичное до десятичного представления:

0000 0000 => 0
0000 0001 => 1 (2^0)
0000 0010 => 2 (2^1 + 2^0)
...
1111 1111 => 255 (2^7 + 2^6 + ... + 2^1)

теперь следующее число естественно, если вы увеличите на 1. добавление 1 к двоичному 1111 1111 приведет к созданию 1 0000 0000

(1) 0000 0000 => -256 !!! обычно бит переполнения в позиции 8 будет представлять знаковый бит (отрицательный вес)

first following value is adding 1 to most-right position 
(1) 0000 0001 => -256 + 2^0 = -255
(1) 0000 0010 => -256 + 2^1 = -254
(1) 0000 0011 => -256 + 2^1 + 2^1 = -253
...

вы получите изображение

Источником этого является реализация основного реестра оборудования, которая основывается на двоичных значениях. Здесь вы можете прочитать более подробное объяснение: http://www.allaboutcircuits.com/textbook/digital/chpt-2/binary-overflow/

Ответ 4

Когда t1 берется после t0 (t1 < t0 = false в реальном слове), и есть поток owerflow для t1 (не t0). t1 отрицательно, и t0 положительный - это случай t1 - t0 < 0 дает вам хороший результат false, потому что двоичная операция "-" не допускает ошибки owerflow и t1 < t0 даст неверный результат: true

Более базовое отрицательное число, если оно читает беззнаковое число, больше, чем подписанное положительное число: https://en.wikipedia.org/wiki/Signed_number_representations и