F.39. seg — un tipo de datos para segmentos de línea o intervalos de coma flotante #

F.39.1. Motivación
F.39.2. Sintaxis
F.39.3. Precisión
F.39.4. Uso
F.39.5. Notas
F.39.6. Créditos

Este módulo implementa un tipo de datos seg para representar segmentos de línea o intervalos de coma flotante. seg puede representar la incertidumbre en los extremos del intervalo, lo que lo hace especialmente útil para representar mediciones de laboratorio.

Este módulo se considera de confianza (trusted), es decir, puede ser instalado por usuarios no superusuarios que tengan el privilegio CREATE en la base de datos actual.

F.39.1. Motivación #

La geometría de las mediciones suele ser más compleja que la de un punto en un continuo numérico. Una medición suele ser un segmento de ese continuo con límites algo difusos. Las mediciones se presentan como intervalos debido a la incertidumbre y la aleatoriedad, así como porque el valor medido puede ser naturalmente un intervalo que indica alguna condición, como el rango de temperatura de estabilidad de una proteína.

Usando solo el sentido común, parece más conveniente almacenar tales datos como intervalos, en lugar de pares de números. In la práctica, incluso resulta más eficiente en la mayoría de las aplicaciones.

Siguiendo con el sentido común, la difuminación (fuzziness) de los límites sugiere que el uso de tipos de datos numéricos tradicionales conduce a una cierta pérdida de información. Considera esto: tu instrumento lee 6.50 y tú ingresas esta lectura en la base de datos. ¿Qué obtienes cuando la recuperas? Observa:

test=> select 6.50 :: float8 as "pH";
 pH
---
6.5
(1 row)

En el mundo de las mediciones, 6.50 no es lo mismo que 6.5. A veces puede ser críticamente diferente. Los experimentadores suelen anotar (y publicar) los dígitos en los que confían. 6.50 es en realidad un intervalo difuso contenido dentro de un intervalo más grande y aún más difuso, 6.5, siendo sus puntos centrales (probablemente) la única característica común que comparten. Definitivamente no queremos que elementos de datos tan diferentes parezcan iguales.

¿Conclusión? Es agradable tener un tipo de datos especial que pueda registrar los límites de un intervalo con precisión arbitrariamente variable. Variable en el sentido de que cada elemento de datos registra su propia precisión.

Mira esto:

test=> select '6.25 .. 6.50'::seg as "pH";
          pH
------------
6.25 .. 6.50
(1 row)

F.39.2. Sintaxis #

La representación externa de un intervalo se forma utilizando uno o dos números de coma flotante unidos por el operador de rango (.. o ...). Alternativamente, se puede especificar como un punto central más o menos una desviación. También se pueden almacenar indicadores de certeza opcionales (<, > o ~). (Sin embargo, los operadores incorporados ignoran los indicadores de certeza). La Table F.29 proporciona una visión general de las representaciones permitidas; la Table F.30 muestra algunos ejemplos.

En la Table F.29, x, y y delta denotan números de coma flotante. A x e y, pero no a delta, les puede preceder un indicador de certeza.

Table F.29. Representaciones externas de seg

xValor único (intervalo de longitud cero)
x .. yIntervalo desde x hasta y
x (+-) deltaIntervalo desde x - delta hasta x + delta
x ..Intervalo abierto con límite inferior x
.. xIntervalo abierto con límite superior x

Table F.30. Ejemplos de entradas válidas para seg

5.0 Crea un segmento de longitud cero (un punto, si se quiere)
~5.0 Crea un segmento de longitud cero y registra ~ en los datos. ~ es ignorado por las operaciones de seg, pero se conserva como un comentario.
<5.0 Crea un punto en 5.0. < es ignorado pero se conserva como un comentario.
>5.0 Crea un punto en 5.0. > es ignorado pero se conserva como un comentario.
5(+-)0.3 Crea un intervalo 4.7 .. 5.3. Ten en cuenta que la notación (+-) no se conserva.
50 .. Todo lo que sea mayor o igual a 50
.. 0Todo lo que sea menor o igual a 0
1.5e-2 .. 2E-2 Crea un intervalo 0.015 .. 0.02
1 ... 2 Lo mismo que 1...2, o 1 .. 2, o 1..2 (se ignoran los espacios alrededor del operador de rango)

Debido a que el operador ... es ampliamente utilizado en fuentes de datos, se permite como una forma alternativa del operador ... Desafortunadamente, esto crea una ambigüedad de análisis: no está claro si el límite superior en 0...23 se refiere a 23 o a 0.23. Esto se resuelve requiriendo al menos un dígito antes del punto decimal en todos los números en la entrada de seg.

Como comprobación de cordura, seg rechaza intervalos con el límite inferior mayor que el superior, por ejemplo 5 .. 2.

F.39.3. Precisión #

Los valores de seg se almacenan internamente como pares de números de coma flotante de 32 bits. Esto significa que los números con más de 7 dígitos significativos serán truncados.

Los números con 7 o menos dígitos significativos conservan su precisión original. Es decir, si tu consulta devuelve 0.00, estarás seguro de que los ceros a la derecha no son artefactos del formato: reflejan la precisión de los datos originales. El número de ceros a la izquierda no afecta a la precisión: se considera que el valor 0.0067 tiene solo 2 dígitos significativos.

F.39.4. Uso #

El módulo seg incluye una clase de operador de índice GiST para valores de seg. Los operadores soportados por la clase de operador GiST se muestran en la Table F.31.

Table F.31. Operadores GiST de seg

Operador

Descripción

seg << segboolean

¿Está el primer seg completamente a la izquierda del segundo? [a, b] << [c, d] es verdadero si b < c.

seg >> segboolean

¿Está el primer seg completamente a la derecha del segundo? [a, b] >> [c, d] es verdadero si a > d.

seg &< segboolean

¿El primer seg no se extiende a la derecha del segundo? [a, b] &< [c, d] es verdadero si b <= d.

seg &> segboolean

¿El primer seg no se extiende a la izquierda del segundo? [a, b] &> [c, d] es verdadero si a >= c.

seg = segboolean

¿Son iguales los dos seg?

seg && segboolean

¿Se superponen los dos seg?

seg @> segboolean

¿Contiene el primer seg al segundo?

seg <@ segboolean

¿Está el primer seg contenido en el segundo?


Además de los operadores anteriores, los operadores de comparación habituales que se muestran en la Table 9.1 están disponibles para el tipo seg. Estos operadores comparan primero (a) con (c), y si son iguales, comparan (b) con (d). Eso resulta en una clasificación razonablemente buena en la mayoría de los casos, lo que resulta útil si deseas utilizar ORDER BY con este tipo.

F.39.5. Notas #

Para ejemplos de uso, consulta la prueba de regresión sql/seg.sql.

El mecanismo que convierte (+-) a rangos regulares no es completamente preciso al determinar el número de dígitos significativos para los límites. Por ejemplo, añade un dígito adicional al límite inferior si el intervalo resultante incluye una potencia de diez:

postgres=> select '10(+-)1'::seg as seg;
      seg
---------
9.0 .. 11             -- debería ser: 9 .. 11

El rendimiento de un índice R-tree puede depender en gran medida del orden inicial de los valores de entrada. Puede ser muy útil ordenar la tabla de entrada por la columna seg; consulta el script sort-segments.pl para ver un ejemplo.

F.39.6. Créditos #

Autor original: Gene Selkov, Jr. , División de Matemáticas y Ciencias de la Computación, Laboratorio Nacional de Argonne.

Mi agradecimiento es principalmente para el Prof. Joe Hellerstein (https://dsf.berkeley.edu/jmh/) por dilucidar la esencia de GiST (http://gist.cs.berkeley.edu/). También estoy agradecido a todos los desarrolladores de Postgres, presentes y pasados, por permitirme crear mi propio mundo y vivir sin perturbaciones en él. Y me gustaría reconocer mi gratitud a Argonne Lab y al Departamento de Energía de los EE. UU. por los años de fiel apoyo a mi investigación de bases de datos.