2 puntos por GN⁺ 11 일 전 | 1 comentarios | Compartir por WhatsApp
  • Acepta como entrada la unión de intervalos disjuntos y puede realizar operaciones aritméticas básicas, llamadas a funciones e incluso potenciación, permitiendo calcular interval union arithmetic directamente en el navegador
  • El intervalo resultado siempre contiene los valores obtenidos al evaluar la misma expresión sobre los números reales elegidos de la unión de entrada, y también puede manejar la división por intervalos que incluyen 0 en forma de unión disjunta
  • En 1 / [-2, 1] produce [-∞, -0.5] U [1, +∞], y en tan([pi/3, 2*pi/3]) produce [-∞, -1.732] U [1.732, +∞], por lo que admite resultados de intervalos discontinuos y representación de límites infinitos
  • Soporta diversas notaciones y funciones como [a, b], [a, b] U [c, d], sintaxis de intervalos anidados, lo, hi, hull, log10, cos, min y max
  • En el modo de precisión completa, devuelve intervalos que envuelven el valor real mediante redondeo hacia afuera basado en IEEE 754 de doble precisión, y destaca por mostrar 0.1 + 0.2 como [0.29999999999999993, 0.3000000000000001]

Resumen

  • Es una calculadora que opera sobre la unión de intervalos disjuntos y soporta la implementación de interval union arithmetic además de los números reales comunes
    • El intervalo [a, b] representa todos los números entre a y b, y [a, b] U [c, d] significa la unión de intervalos separados entre sí
    • Es una extensión de la aritmética de intervalos convencional y permite calcular incluso la división por intervalos que contienen 0 manteniendo la propiedad de clausura
  • Garantía de contención
    • Si se elige arbitrariamente un número real de cada una de las uniones de entrada y se evalúa la misma expresión sobre los reales, ese resultado queda necesariamente incluido en la unión de salida
  • Permite expresar incertidumbre
    • Se da como ejemplo el resultado [450, 550] para 50 * (10 + [-1, 1])
  • Soporta el cálculo de expresiones complejas con intervalos
    • Se puede introducir una expresión como ( [5, 10] U [15, 16] ) / [10, 100] usando el operador U
    • Se muestra como ejemplo el resultado [0.05, 1.6]
  • El resultado de una operación puede ser una unión disjunta
    • 1 / [-2, 1] da como resultado [-∞, -0.5] U [1, +∞]
    • tan([pi/3, 2*pi/3]) da como resultado [-∞, -1.732] U [1.732, +∞]
  • En el modo de precisión completa puede usarse como una calculadora normal, pero además devuelve intervalos que envuelven el valor real, incluidos los problemas de precisión de punto flotante
    • Se presenta el ejemplo 0.1 + 0.2 con resultado [0.29999999999999993, 0.3000000000000001]

Sintaxis

  • Soporte para notación básica
    • Admite la notación de intervalos [a, b]
    • Ejemplo: [0.5, 0.6]
  • Soporte para notación de unión
    • Admite la forma [a, b] U [c, d]
    • Ejemplo: [0, 1] U [5, 6]
  • Soporta operaciones aritméticas básicas y potenciación
    • Suma A + B, ejemplo ➤ [90, 100] + [-2, 2], resultado [88, 102]
    • Resta A - B, ejemplo ➤ [14, 16] - [8, 12], resultado [2, 8]
    • Multiplicación A * B, ejemplo ➤ [-5, 10] * [2, 4], resultado [-20, 40]
    • División A / B, ejemplo ➤ [2, 4] / [-1, 2], resultado [-∞, -2] U [1, +∞]
    • Potenciación A ^ B, ejemplo ➤ [2, 3] ^ [-2, 3], resultado [0.1111, 27]
  • Soporte para funciones y constantes
    • Admite llamadas a función en la forma function(...)
    • log10([1, 10000]) da como resultado [0, 4]
    • Admite introducir nombres de constantes
    • pi da como resultado [3.1415926535897927, 3.1415926535897936]
  • Se pueden mezclar números e intervalos en la entrada
    • Se pueden introducir intervalos con la sintaxis de corchetes, como [1, 2]
    • Un número como 3.14 se interpreta como un intervalo estrecho de ancho 0, [3.14, 3.14]
    • En el modo de precisión completa hay diferencias de detalle relacionadas con esto
    • 1.55 + [-0.002, 0.002] da como resultado [1.548, 1.552]
  • Soporta sintaxis de intervalos anidados
    • Se puede introducir [0, [0, 100]] y el resultado es [0, 100]
    • Incluso los números internos que definen los límites del intervalo se interpretan todos como intervalos
    • En los intervalos anidados, un intervalo colocado en una posición de límite toma el límite superior de ese intervalo
    • Este diseño permite aplicar aritmética al propio límite
    • [0, cos(2*pi)] da como resultado [0, 1]

Funciones compatibles

  • Soporte para constantes
    • Soporta inf, , pi y e
    • [-inf, 0] * [-inf, 0] da como resultado [0, +∞]
  • Soporte para funciones de extracción de límites
    • lo(A) devuelve el límite inferior
      • lo([1, 2]) da como resultado [1, 1]
    • hi(A) devuelve el límite superior
      • hi([1, 2]) da como resultado [2, 2]
  • Soporte para cálculo de envolvente de intervalo
    • hull(A) envuelve la unión en un solo intervalo
    • hull([1, 2] U [99, 100]) da como resultado [1, 100]
  • Soporte para funciones matemáticas básicas
    • abs(A), ejemplo abs([-10, 5]), resultado [0, 10]
    • sqrt(A), ejemplo sqrt([9, 49]), resultado [3, 7]
    • sqinv(A), ejemplo sqinv([4, 64]), resultado [-8, -2] U [2, 8]
  • Soporte para funciones logarítmicas y exponenciales
    • log(A), ejemplo log([0, 1]), resultado [-∞, 0]
    • log2(A), ejemplo log2([64, 1024]), resultado [6, 10]
    • log10(A), ejemplo log10([0.0001, 1]), resultado [-4, 0]
    • exp(A), ejemplo exp([-∞, 0] U [1, 2]), resultado [0, 1] U [2.718, 7.389]
  • Soporte para funciones trigonométricas e inversas trigonométricas
    • cos(A), ejemplo cos([pi/3, pi]), resultado [-1, 0.5]
    • sin(A), ejemplo sin([pi/6, 5*pi/6]), resultado [0.5, 1]
    • tan(A), ejemplo tan([pi/3, 2*pi/3]), resultado [-∞, -1.732] U [1.732, +∞]
    • acos(A), ejemplo acos([-1/2, 1/2]), resultado [1.047, 2.094]
    • asin(A), ejemplo asin([0, 1]), resultado [0, 1.571]
    • atan(A), ejemplo atan([-10, 2]), resultado [-1.471, 1.107]
  • Soporte para funciones de mínimo y máximo
    • min(A, B), ejemplo min([1, 2], [0, 6]), resultado [0, 2]
    • max(A, B), ejemplo max([0, 10], [5, 6]), resultado [5, 10]

Modo de precisión completa

  • Implementa redondeo hacia afuera sobre punto flotante IEEE 754 de doble precisión
    • Usa el tipo number de JavaScript
    • Garantiza que el intervalo resultado siempre contiene el valor real de calcular la misma expresión sobre los reales con precisión infinita
  • Incluye el caso de 0.1 + 0.2
    • 0.3 no puede representarse exactamente como punto flotante de doble precisión
    • La aritmética de intervalos calcula un intervalo que contiene 0.3
  • Comportamiento al activar el modo de precisión completa
    • Los números introducidos por el usuario se interpretan como el intervalo más pequeño que contiene el valor IEEE 754 más cercano a la representación decimal escrita, pero cuyos dos límites no son iguales a ese valor
    • Los números de salida se muestran con todos los dígitos decimales disponibles
    • Usa Number.toString()
  • Comportamiento al desactivar el modo de precisión completa
    • Los números introducidos por el usuario se interpretan como un intervalo degenerado cuyos dos límites son iguales al valor IEEE 754 más cercano a la representación decimal escrita
    • Los números de salida se muestran con un máximo de 4 decimales
    • Usa Number.toPrecision()

Errores

  • Se menciona que es posible que aún queden errores en la calculadora
  • Se proporciona un enlace de GitHub Issues como vía para reportar problemas

Código abierto

  • Tanto Interval Calculator como el motor de cálculo not-so-float están publicados como código abierto
  • Incluye un enlace de patrocinio en GitHub Sponsors

Trabajo futuro

  • Está previsto dividir el modo de precisión completa en dos controles
    • Interpretación de entrada
    • Precisión de visualización
  • Está previsto añadir la variable ans
    • Variable para guardar el resultado de la entrada anterior
  • Está previsto añadir un operador o función de intersección
  • Está previsto mejorar la intuición de la precedencia del operador U
  • Está previsto admitir la entrada de unión vacía

1 comentarios

 
GN⁺ 11 일 전
Comentarios en Hacker News
  • Hablando como autor, el redondeo hacia afuera es lo más conocido en la aritmética de intervalos para lidiar con problemas de precisión, pero me da pena que toda la atención se la lleve eso. La propiedad de inclusión de la que hablan los artículos funciona en todas las escalas, y por eso salen resultados naturales como 50 * (10 + [-1, 1]) = [450, 550]. Si encima le agregas una capa de unions, también puedes manejar cosas como la verdadera inversa de la función cuadrado, y se entiende mejor si pruebas sqinv(64) en lugar de sqrt. En realidad, este interval calculator lo hice para probar una implementación de arithmetic de uniones de intervalos que venía desarrollando para otro proyecto, una hoja de cálculo con actualización hacia atrás. La implementación está en not-so-float, y los proyectos relacionados son bidicalc y la discusión en HN
    • Me da curiosidad en qué se diferencia la arithmetic implementada del estándar IEEE 1788. También me gustaría saber qué relación tienen con ese estándar los dos artículos enlazados. Para resolver los problemas mencionados en el post, ¿hacía falta empezar completamente desde cero, o se podría haber construido sobre el estándar IEEE?
    • Está buenísimo y pienso seguir jugando con esto. Hay dos cosas que me dan mucha curiosidad: primero, qué tan difícil sería agregar funciones multivaluadas. Por ejemplo, estaría genial poder obtener el conjunto completo [pi/2, pi/2] + n[2pi, 2pi] para asin(1) sin tener que recurrir a Mathematica. Segundo, la redacción sobre cómo se interpretan los números que ingresa el usuario me confundió un poco. Según entiendo, los valores límite de salida del intervalo más pequeño que contiene el valor de entrada deberían ser los dos números IEEE 754 más cercanos que lo encierran, pero tal como está escrito suena más como IEEE754(input)+[-epsilon, epsilon], y eso se siente distinto
  • Esto está realmente bueno. También vale la pena ver el trabajo de Matt Keeter sobre superficies implícitas y optimización usando interval math. Puedes ver algo relacionado en esta charla
  • Yo también tengo una calculadora de gráficas hecha con interval arithmetic, así que quizá te interese. Está formulagraph para probarla directamente, y en este post expliqué cómo funciona y puse el código relacionado
    • Mi primera impresión fue que se parecía a GrafEq. Me recordó al viejo GrafEq
  • A mí también me pareció divertido esto y alguna vez escribí una librería sencilla de Math::Interval en Raku. Es raku-Math-Interval, un experimento construido sobre las Junction integradas de Raku y la clase Range, y fue una experiencia bastante interesante
  • Muy bueno, y gracias por compartirlo. Creo que estaría aún mejor si en los intervalos se indicara si incluyen o no los límites superior e inferior. La notación a la que estoy acostumbrado usa corchetes orientados hacia afuera cuando el valor no está incluido, y siempre igual para infinito. Por ejemplo, ]-∞, -1] U [0.5, +∞[; entonces el intervalo excluido del medio sería ]-1, 0.5[. Por lo que entendí, min y max también parecen interpretarse de esa manera. Y otra idea de UI que sería cómoda: que al hacer clic o tocar una fórmula en el área de resultados, se copie al campo de entrada
    • Al leer el artículo enlazado, vi que aquí solo se describían intervalos cerrados. Una unión de intervalos se define como un conjunto de intervalos cerrados y separados entre sí, y solo los límites de los intervalos extremos pueden ser ±∞
    • Se podría soportar una notación así, pero el código se volvería mucho más complejo. Por eso decidí bastante temprano no darle soporte. Aun así, podría ser una mejora interesante
    • A mí también me confundió un poco esa parte. La notación estándar que yo conocía usaba paréntesis redondos, aunque supongo que en entornos ASCII eso quizá no encaje muy bien
  • Está muy genial. No entendí todas las operaciones por completo, pero incluso lo que sí entendí ya me pareció bastante impresionante. Me habría gustado encontrarme antes en clase con la aritmética sobre intervalos. Ya aparecen ideas parecidas en cosas como los intervalos de confianza de estadística básica o el ± de las ecuaciones cuadráticas, pero siempre me frustró un poco no poder seguir calculando con el resultado como si fuera un solo dato, y tener que tratar por separado los dos valores del ± cada vez. Claro, entiendo por qué los profesores quieren volver rápido a las aplicaciones y no profundizan demasiado. Aun así, me habría gustado al menos una pista de que también es posible hacer aritmética general con este tipo de objetos. Lo que muestras aquí va mucho más allá de eso, pero se siente como una confirmación de que tiene sentido pensar en los intervalos como datos con comportamiento propio
  • Ojalá hubiera conocido la interval arithmetic cuando empecé a usar tick, la librería de intervalos temporales en Clojure. También incluye una implementación de Allen's Interval Algebra, y adopta la noción de conjuntos discretos de intervalos, que sirve mucho para cálculos prácticos. Por ejemplo, encaja bien para tareas de RR. HH. como calcular el conjunto de intervalos de vacaciones dentro de un año. Yo solo conocía el trabajo de Allen, y por casualidad terminé descubriendo las ventajas de este tipo de conjuntos. El código está en juxt/tick
  • Le veo bastante utilidad a esta herramienta, pero personalmente creo que una calculadora probabilística me sería más útil. Por ejemplo, un resultado como 1 / [-1, 2] no te dice qué valores son más o menos plausibles, y aun suponiendo que la entrada sea uniforme, la salida claramente no parece seguir una distribución uniforme
  • Yo también implementé hace poco algo parecido, pero desde la perspectiva de la pertenencia a conjuntos. Por eso necesitaba la operación de complemento para hacer un análisis booleano completo sobre pertenencia a intervalos. Aquí todos los intervalos son conjuntos cerrados, así que su complemento serían intervalos abiertos, pero para mi caso de uso no importaba si los extremos estaban incluidos o no, así que no hice una distinción estricta entre intervalos abiertos y cerrados. Además, con arithmetic inexacta puede que ni siquiera esté bien definido si un conjunto es abierto o cerrado
  • Se ve genial haber extendido la lógica a unions of intervals, pero me da curiosidad la complejidad. Si una sola operación ya puede producir dos intervalos, parece que tras N operaciones podría haber un crecimiento exponencial en algunos casos. Entonces me preocupa que eso lo vuelva poco práctico para usos comunes como la abstract interpretation, a menos que se introduzcan aproximaciones a partir de cierta cantidad
    • Sí, es una observación acertada, y este problema es bien conocido en abstract interpretation. Como dices, normalmente se pone un límite al tamaño del objeto y, cuando se supera, se fusionan los intervalos. Aunque al menos en abstract interpretation me parece que muchas veces también se usan dominios más refinados que los simples intervalos