unidos tipos son mexico mexicana las italia estados españa entre ejemplos diferencias culturales cultura cuales alemania java time comparison integer-overflow

java - tipos - ¿Cómo comparar dos valores de tiempo nano?



diferencias culturales entre mexico y estados unidos (4)

Bueno, javadoc dice la verdad. Considere este ejemplo:

long t0 = Long.MAX_VALUE; long t1 = Long.MIN_VALUE; System.out.println(t1 < t0); System.out.println(t1 - t0 < 0);

Dará

true false

mientras que matemáticamente ambas expresiones son verdaderas. Pero en nuestro caso, sabemos que el valor negativo del time significa que está desbordado, por lo tanto, debería ser realmente mayor que el número positivo.

He leído el javadoc para System.nanoTime() y todo parece claro. Hasta que llegué al párrafo final:

Para comparar dos valores de nano tiempo

long t0 = System.nanoTime();

...

long t1 = System.nanoTime();

se debe usar t1 - t0 <0, no t1 <t0, debido a la posibilidad de un desbordamiento numérico.

Hay dos cosas que no están claras para mí:

  1. ¿Por qué se comprueba si t1 < t0 si se tomó t1 después de t0 ? Mi entendimiento es que el tiempo nano siempre está aumentando. Por lo tanto, prefiero comprobar t1 > t0 .
  2. Supongamos que es un error tipográfico, y significaron que la comprobación correcta es t1 - t0 > 0 . Todavía no entiendo por qué esa es la forma correcta de verificar y no t1 > t0 . Mencionan el desbordamiento numérico y no entiendo lo que quieren decir. Respecto al desbordamiento numérico, esto es lo que se menciona:

Las diferencias en llamadas sucesivas que abarcan más de aproximadamente 292 años (2 ^ 63 nanosegundos) no calcularán correctamente el tiempo transcurrido debido a un desbordamiento numérico.

OK, así como el tiempo nano se almacena como un valor largo, eventualmente se desbordará en 292 años. ¿Y qué pasa después? ¿Comienza desde el principio, es decir, el valor negativo más bajo -2 ^ 63? ¿O deja de medir y vuelve (2 ^ 63 - 1) siempre?


Cuando t1 se toma después de t0 (t1 <t0 = falso en palabra real) y hay un flujo de flujo para t1 (no t0). t1 es negativo y t0 positivo en este caso t1 - t0 <0 le da el buen resultado falso porque la operación binaria ''-'' no cometa errores en el flujo de flujo y t1 <t0 le dará un resultado incorrecto: verdadero

Un número negativo más básico si lee un número no firmado es más grande que un número positivo firmado: https://en.wikipedia.org/wiki/Signed_number_representations and


Déjame empezar desde el final de tu pregunta. Sí, en caso de que el valor sea mayor que 2 ^ 63-1, el valor se desbordará. La implementación común de un desbordamiento es que se almacenan los bits representables menos significativos del resultado; el valor se ajustará (se puede ver en la parte inferior de mi publicación sobre desbordamiento como referencia)

La secuencia es como: 2^63-2, 2^63-1, -2^63, -(2^63-1) ...

Ahora, mirando de nuevo a Javadoc, estoy de acuerdo en que la explicación sobre el uso de la comparación es confusa y que, naturalmente, intentaríamos comparar t1 > t0 para validar si t1 sucedió después de t0 . Estás parcialmente en lo cierto. Aunque no creo que sea un error tipográfico, pero no se explica correctamente . Creo que debería decir:

Para dos valores t0 y t1 (donde t1 se captura después de t0), no debe usar t1 < t0 (para verificar si es false ) sino t1 - t0 < 0 , de manera similar, no debe usar t1 > t0 (para verificar si es true ) sino más bien t1 - t0 > 0

O para formalizarlo:

Para dos valores ''nano'' t0 y t1 , donde t1 se captura después de t0 siguientes posiciones: (t1 - t0 > 0) == true siempre que el período entre t1 y t0 sea ​​<= 2 ^ 63 ns.

Por que Debido a que incluso cuando t1 desborda (por lo que es negativo), el resultado t1 - t0 también será negativo , pero será menor que -2 ^ 64 y se "desbordará" a un valor positivo. .

¡Esto se mantiene mientras se cumpla la condición sobre la distancia entre t0 y t1 ! En caso de que la distancia sea mayor que 2 ^ 64 por ejemplo: para t0 = 1; t1 = -(2^64-2) t0 = 1; t1 = -(2^64-2) , el resultado de la resta sería: t1 - t0 = -(2^64-1) por lo que la condición especificada ( t1 - t0 > 0 ) dará un resultado incorrecto.

¿Derecha?:)

En desbordamiento

En aras de la explicación, lats asume un tipo que se almacena utilizando 8 bits (en lugar de 64 utilizados por largo), por lo que la representación de binario a decimal es

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

ahora el siguiente número es naturalmente cuando incrementaría en 1. si agrega 1 al binario 1111, 1111 producirá 1 0000 0000

(1) 0000 0000 => -256 !!! por lo general, el bit de sobrevuelo en una posición 8 representará un bit de signo (peso negativo)

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 ...

te dan la imagen

El origen de esto está en la implementación del registro de hardware subyacente que se basa en valores binarios. Puede leer una explicación más detallada, por ejemplo, aquí: http://www.allaboutcircuits.com/textbook/digital/chpt-2/binary-overflow/


Tiene razón, las partes de la documentación que citó parecen estar un poco confundidas.

Sin embargo, la parte de la documentación que cuenta es esta:

Este método solo se puede utilizar para medir el tiempo transcurrido y no está relacionado con ninguna otra noción del sistema o del reloj de pared. El valor devuelto representa nanosegundos desde un tiempo de origen fijo pero arbitrario (quizás en el futuro, por lo que los valores pueden ser negativos) . El mismo origen es utilizado por todas las invocaciones de este método en una instancia de una máquina virtual Java; Es probable que otras instancias de máquinas virtuales utilicen un origen diferente.

(énfasis agregado por mi).

Lo que esto significa es que no tiene ninguna garantía de que su código no se esté ejecutando en el momento en que el valor largo producido pasará de positivo a negativo.

No hay nada que garantice que esto sucederá dentro de 300 años, puede suceder hoy.

Actualmente, mi JVM devuelve un número como 3496793269188, pero podría, si así lo quisiera, devolver un número muy cercano al 9223372036854775807 (que es Long.MAX_VALUE ), lo que haría un cambio de positivo a negativo inminente.

Por lo tanto, debe tomar todas las precauciones necesarias.