que punto online numeros notaciĆ³n normalizada informatica flotante ejemplos coma compression floating-point time-series

compression - punto - Comprimir datos de coma flotante



punto flotante plc (7)

Aquí hay algunas ideas si desea crear su propio algoritmo simple:

  • Use xor del valor actual con el valor anterior para obtener un conjunto de bits que describa la diferencia.
  • Divida esta diferencia en dos partes: una parte son los "bits de mantisa" y una parte son los "bits de exponente".
  • Utilice la codificación de longitud variable (diferente número de bits / bytes por valor) o cualquier método de compresión que elija para guardar estas diferencias. Puede usar flujos separados para mantisas y exponentes, ya que las mantisas tienen más bits para comprimir.
  • Es posible que esto no funcione bien si alterna entre dos fuentes de flujos de tiempo-valor diferentes. Por lo tanto, puede que tenga que comprimir cada fuente en una secuencia o bloque por separado.
  • Para perder precisión, puede soltar los bits o bytes menos significativos de la mantisa, dejando el exponente intacto.

¿Hay algún método de compresión sin pérdida que se pueda aplicar a datos de coma flotante de series de tiempo, y superará significativamente, digamos, escribir los datos como binarios en un archivo y ejecutarlos a través de gzip?

La reducción de la precisión puede ser aceptable, pero debe suceder de forma controlada (es decir, debo ser capaz de establecer un límite de cuántos dígitos se deben guardar)

Estoy trabajando con algunos archivos de datos grandes que son series de double correlacionados, que describen una función del tiempo (es decir, los valores están correlacionados). Generalmente no necesito la double precisión completa, pero podría necesitar más que float .

Dado que existen métodos especializados sin pérdidas para imágenes / audio, me preguntaba si existe algo especializado para esta situación.

Aclaración: estoy buscando herramientas prácticas existentes en lugar de un documento que describa cómo implementar algo como esto. Algo similar a gzip en velocidad sería excelente.


Dado que usted declara que necesita una precisión en algún lugar entre ''flotante'' y ''doble'': puede poner a cero cualquier cantidad de bits menos significativos en flotantes de precisión simple y doble. Los numers de coma flotante IEEE-754 se representan binaria aproximadamente como seeefffffffff , que representa el valor

signo * 1.fffffff * 2 ^ (eee).

Puede poner a cero la fracción menos significativa (f) bits. Para los flotadores de precisión simple (32 bits), hay 23 fracciones de los cuales puede poner a cero hasta 22. Para la precisión doble (64 bits), es 52 y hasta 51. (Si pone a cero todos los bits , entonces los valores especiales NaN y +/- inf se perderán).

Especialmente si los datos representan valores decimales como 1.2345, esto ayudará a la compresión de datos. Esto se debe a que 1.2345 no se puede representar exactamente como un valor de punto flotante binario, sino más bien como 0x3ff3c083126e978d , que no es 0x3ff3c083126e978d con la compresión de datos. Cortar los 24 bits menos significativos dará como resultado 0x3ff3c08312000000 , que sigue siendo exacto a aproximadamente 9 dígitos decimales (en este ejemplo, la diferencia es 1.6e-9).

Si hace esto en los datos brutos, y luego almacena las diferencias entre los números subsiguientes, será aún más amigable con la compresión (a través de gzip) si los datos brutos varían lentamente.

Aquí hay un ejemplo en C:

#include <inttypes.h> double double_trunc(double x, int zerobits) { // mask is e.g. 0xffffffffffff0000 for zerobits==16 uint64_t mask = -(1LL << zerobits); uint64_t floatbits = (*((uint64_t*)(&x))); floatbits &= mask; x = * ((double*) (&floatbits)); return x; }

Y uno en python / numpy:

import numpy as np def float_trunc(a, zerobits): """Set the least significant <zerobits> bits to zero in a numpy float32 or float64 array. Do this in-place. Also return the updated array. Maximum values of ''nzero'': 51 for float64; 22 for float32. """ at = a.dtype assert at == np.float64 or at == np.float32 or at == np.complex128 or at == np.complex64 if at == np.float64 or at == np.complex128: assert nzero <= 51 mask = 0xffffffffffffffff - (1 << nzero) + 1 bits = a.view(np.uint64) bits &= mask elif at == np.float32 or at == np.complex64: assert nzero <= 22 mask = 0xffffffff - (1 << nzero) + 1 bits = a.view(np.uint32) bits &= mask return a



Posibles métodos que se pueden usar para la compresión de coma flotante:

Puede probar todos estos métodos, con sus datos, utilizando la herramienta icapp para Linux y Windows.


Puede usar el algoritmo de suavizado exponencial de Holt (que es un algoritmo de compresión basado en la predicción). Inicialmente, asigne un poco de peso a los datos y pronostique el siguiente valor. Si ambos datos son los mismos, produce muchos ceros en el MSB al hacer la operación XOR.


Una de las técnicas que usan los HDF5 es "barajar", donde se agrupan cada byte para N valores de coma flotante. Es más probable que esto le proporcione secuencias repetitivas de bytes que se comprimirán mejor con gzip, por ejemplo .

Un segundo método que he encontrado que reduce en gran medida el tamaño de los datos comprimidos con gzip es convertir primero los datos al formato float16 (media precisión) y viceversa a float32. Esto produce muchos ceros en la secuencia de salida que puede reducir el tamaño de los archivos en un 40-60 por ciento después de la compresión. Una sutilidad es que el valor máximo de float16 es bastante bajo, por lo que es posible que desee escalar sus datos primero, por ejemplo, en python

import numpy as np import math input = np.array(...) # format can only hold 65504 maximum, so we scale input data log2max = int(math.log(np.nanmax(input), 2)) scale = 2**(log2max - 14) scaled = input * (1./scale) # do the conversion to float16 temp_float16 = np.array(scaled, dtype=np.float16) # convert back again and rescale output = np.array(temp_float16, dtype=np.float32) * scale

Algunas pruebas sugieren que la diferencia fraccional absoluta media entre la entrada y la salida para algunos datos es de alrededor de 0,00019 con un máximo de 0,00048. Esto está en línea con la precisión 2 ** 11 de la mantisa.


Ya que está pidiendo herramientas existentes, tal vez zfp haga el truco.