2 pontos por GN⁺ 11 일 전 | 1 comentários | Compartilhar no WhatsApp
  • Recebe como entrada a união de intervalos separados, executa as quatro operações aritméticas, chamadas de função e até potenciação, permitindo calcular interval union arithmetic diretamente no navegador
  • O intervalo resultante sempre inclui os valores obtidos ao calcular a mesma expressão nos reais com valores escolhidos da união de entrada, e até a divisão por intervalos que incluem 0 pode ser tratada na forma de uniões separadas
  • Em casos como 1 / [-2, 1], o resultado é [-∞, -0.5] U [1, +∞], e em tan([pi/3, 2*pi/3]), [-∞, -1.732] U [1.732, +∞], com suporte a resultados em intervalos descontínuos e representação de limites infinitos
  • Suporta diversas notações e funções, como [a, b], [a, b] U [c, d], sintaxe de intervalos aninhados, lo, hi, hull, log10, cos, min e max
  • No modo de precisão total, retorna intervalos que envolvem o valor real com arredondamento para fora baseado em IEEE 754 de dupla precisão, destacando-se por mostrar 0.1 + 0.2 como [0.29999999999999993, 0.3000000000000001]

Visão geral

  • É uma calculadora voltada a uniões de intervalos separados, com suporte não só a números reais comuns, mas também à implementação de interval union arithmetic
    • O intervalo [a, b] representa todos os números de a até b, e [a, b] U [c, d] significa a união de intervalos separados entre si
    • É uma extensão da aritmética intervalar comum, e até a divisão por intervalos que contêm 0 pode ser calculada preservando a propriedade de fechamento
  • Garantia de inclusão
    • Se for escolhido arbitrariamente um número real de cada união de entrada e a mesma expressão for calculada sobre os reais, o resultado estará necessariamente contido na união de saída
  • Permite expressar incerteza
    • É dado o exemplo de 50 * (10 + [-1, 1]), cujo resultado é [450, 550]
  • Suporta o cálculo de expressões intervalares complexas
    • É possível inserir expressões como ( [5, 10] U [15, 16] ) / [10, 100] usando o operador U
    • É dado o exemplo de resultado [0.05, 1.6]
  • O resultado das operações pode ser uma união separada
    • 1 / [-2, 1] resulta em [-∞, -0.5] U [1, +∞]
    • tan([pi/3, 2*pi/3]) resulta em [-∞, -1.732] U [1.732, +∞]
  • No modo de precisão total, ela pode ser usada como uma calculadora comum, mas ainda fornece resultados intervalares que envolvem o valor real, incluindo problemas de precisão de ponto flutuante
    • É mostrado o exemplo de 0.1 + 0.2, cujo resultado é [0.29999999999999993, 0.3000000000000001]

Sintaxe

  • Suporte à notação básica
    • Suporta a notação de intervalo [a, b]
    • Exemplo: [0.5, 0.6]
  • Suporte à notação de união
    • Suporta a forma [a, b] U [c, d]
    • Exemplo: [0, 1] U [5, 6]
  • Suporte às quatro operações e à potenciação
    • Adição A + B exemplo ➤ [90, 100] + [-2, 2] resultado [88, 102]
    • Subtração A - B exemplo ➤ [14, 16] - [8, 12] resultado [2, 8]
    • Multiplicação A * B exemplo ➤ [-5, 10] * [2, 4] resultado [-20, 40]
    • Divisão A / B exemplo ➤ [2, 4] / [-1, 2] resultado [-∞, -2] U [1, +∞]
    • Potenciação A ^ B exemplo ➤ [2, 3] ^ [-2, 3] resultado [0.1111, 27]
  • Suporte a funções e constantes
    • Suporta chamadas no formato function(...)
    • log10([1, 10000]) resulta em [0, 4]
    • Suporta inserir nomes de constantes
    • pi resulta em [3.1415926535897927, 3.1415926535897936]
  • Entrada mista de números e intervalos
    • É possível inserir intervalos com a sintaxe de colchetes, como em [1, 2]
    • Números como 3.14 são interpretados como um intervalo estreito de largura 0, [3.14, 3.14]
    • No modo de precisão total, há diferenças detalhadas relacionadas a isso
    • 1.55 + [-0.002, 0.002] resulta em [1.548, 1.552]
  • Suporte à sintaxe de intervalos aninhados
    • É possível inserir [0, [0, 100]], e o resultado é [0, 100]
    • Até os números internos que definem os limites do intervalo são interpretados como intervalos
    • Em intervalos aninhados, o intervalo colocado na posição do limite passa a usar o limite superior desse intervalo
    • Esse design permite aplicar aritmética ao próprio limite
    • [0, cos(2*pi)] resulta em [0, 1]

Funções suportadas

  • Suporte a constantes
    • Suporta inf, , pi, e
    • [-inf, 0] * [-inf, 0] resulta em [0, +∞]
  • Suporte a funções de extração de limites
    • lo(A) retorna o limite inferior
      • lo([1, 2]) resulta em [1, 1]
    • hi(A) retorna o limite superior
      • hi([1, 2]) resulta em [2, 2]
  • Suporte ao cálculo do invólucro do intervalo
    • hull(A) envolve a união em um único intervalo
    • hull([1, 2] U [99, 100]) resulta em [1, 100]
  • Suporte a funções matemáticas básicas
    • abs(A) exemplo abs([-10, 5]) resultado [0, 10]
    • sqrt(A) exemplo sqrt([9, 49]) resultado [3, 7]
    • sqinv(A) exemplo sqinv([4, 64]) resultado [-8, -2] U [2, 8]
  • Suporte a funções logarítmicas e exponenciais
    • log(A) exemplo log([0, 1]) resultado [-∞, 0]
    • log2(A) exemplo log2([64, 1024]) resultado [6, 10]
    • log10(A) exemplo log10([0.0001, 1]) resultado [-4, 0]
    • exp(A) exemplo exp([-∞, 0] U [1, 2]) resultado [0, 1] U [2.718, 7.389]
  • Suporte a funções trigonométricas e trigonométricas inversas
    • cos(A) exemplo cos([pi/3, pi]) resultado [-1, 0.5]
    • sin(A) exemplo sin([pi/6, 5*pi/6]) resultado [0.5, 1]
    • tan(A) exemplo tan([pi/3, 2*pi/3]) resultado [-∞, -1.732] U [1.732, +∞]
    • acos(A) exemplo acos([-1/2, 1/2]) resultado [1.047, 2.094]
    • asin(A) exemplo asin([0, 1]) resultado [0, 1.571]
    • atan(A) exemplo atan([-10, 2]) resultado [-1.471, 1.107]
  • Suporte a funções de mínimo e máximo
    • min(A, B) exemplo min([1, 2], [0, 6]) resultado [0, 2]
    • max(A, B) exemplo max([0, 10], [5, 6]) resultado [5, 10]

Modo de precisão total

  • Implementa arredondamento para fora sobre ponto flutuante IEEE 754 de dupla precisão
    • Usa o tipo number do JavaScript
    • Garante que o intervalo resultante sempre contenha o valor real obtido ao calcular a mesma expressão sobre os reais com precisão infinita
  • Inclui o caso 0.1 + 0.2
    • 0.3 não pode ser representado exatamente em ponto flutuante de dupla precisão
    • A interval arithmetic realiza um cálculo intervalar que inclui 0.3
  • Com o modo de precisão total ativado
    • Os números inseridos pelo usuário são interpretados como o menor intervalo que contém o valor IEEE 754 mais próximo da representação decimal digitada, com ambos os limites diferentes desse valor
    • Os números de saída são exibidos com todos os dígitos decimais disponíveis
    • Usa Number.toString()
  • Com o modo de precisão total desativado
    • Os números inseridos pelo usuário são interpretados como um intervalo degenerado cujos dois limites são iguais ao valor IEEE 754 mais próximo da representação decimal digitada
    • Os números de saída são exibidos com no máximo 4 casas decimais
    • Usa Number.toPrecision()

Bugs

  • É mencionado que ainda pode haver bugs na calculadora
  • É fornecido um link de GitHub Issues como canal para relatar problemas

Código aberto

  • Tanto o Interval Calculator quanto o motor da calculadora, not-so-float, são publicados como open source
  • Inclui link de apoio via GitHub Sponsors

Trabalhos futuros

  • O modo de precisão total será dividido em dois controles
    • interpretação da entrada
    • precisão de exibição
  • Será adicionada a variável ans
    • variável para armazenar o resultado da entrada anterior
  • Será adicionado um operador ou função de interseção
  • A intuitividade da precedência do operador U será melhorada
  • Haverá suporte para entrada de união vazia

1 comentários

 
GN⁺ 11 일 전
Comentários do Hacker News
  • Falando como autor, arredondamento para fora é a parte mais conhecida da interval arithmetic por causa dos problemas de precisão, mas acho uma pena que só isso receba atenção. A propriedade de inclusão de que os artigos falam funciona em qualquer escala, e por isso resultados como 50 * (10 + [-1, 1]) = [450, 550] saem de forma natural. Quando você acrescenta uma camada de union, também dá para lidar com coisas como a verdadeira inversa da função quadrática, e isso fica claro se você testar sqinv(64) em vez de sqrt. Na verdade, este interval calculator foi feito para testar uma implementação de interval union arithmetic que eu estava criando para outro projeto, a backwards updating spreadsheet. A implementação está em not-so-float, e os projetos relacionados são bidicalc e esta discussão no HN
    • Fiquei curioso sobre como a arithmetic implementada difere do padrão IEEE 1788. Também queria entender qual é a relação dos dois artigos linkados com esse padrão. Para resolver os problemas mencionados no texto, foi preciso recomeçar do zero, ou daria para construir em cima do padrão IEEE?
    • Isso ficou realmente muito legal, e pretendo brincar mais com isso. Tenho curiosidade sobre duas coisas em especial. Primeiro, quão difícil seria adicionar funções multivaloradas. Por exemplo, seria ótimo poder obter o conjunto completo [pi/2, pi/2] + n[2pi, 2pi] para asin(1) sem precisar do Mathematica. Segundo, a frase explicando como os números digitados pelo usuário são interpretados me pareceu um pouco confusa. Pelo que entendi, os valores-limite de saída do menor intervalo que contém o valor de entrada deveriam ser os dois números IEEE 754 mais próximos que envolvem essa entrada; mas, do jeito que está escrito, soa mais como IEEE754(input)+[-epsilon, epsilon], o que parece ter outro significado
  • Isso é muito bom. O trabalho do Matt Keeter com implicit surfaces e otimização usando interval math também vale muito a pena ver. Dá para conferir algo relacionado nesta apresentação
  • Também tenho uma calculadora gráfica feita com interval arithmetic, então talvez isso te interesse. Dá para experimentar diretamente no formulagraph, e esta postagem explica como funciona e mostra o código relacionado
    • Minha primeira impressão foi que isso parece GrafEq. Fez lembrar o antigo GrafEq
  • Também achei isso divertido e já escrevi uma biblioteca simples de Math::Interval em Raku. É a raku-Math-Interval, um experimento baseado nos Junctions nativos e na classe Range do Raku, e foi uma experiência bem interessante
  • Muito bom, e obrigado por compartilhar. Acho que seria ainda melhor se os intervalos mostrassem se incluem ou não os limites superior e inferior. A notação com que estou acostumado usa colchetes voltados para fora quando o valor não está incluído, e aplica isso sempre ao infinito também. Por exemplo, ]-∞, -1] U [0.5, +∞[; aí o intervalo excluído no meio seria ]-1, 0.5[. Pelo que entendi, min e max também parecem ser interpretados dessa forma. E uma ideia de UI que talvez fosse útil seria poder clicar ou tocar a expressão na área de resultado para copiá-la para o campo de entrada
    • Lendo o artigo linkado, vi que ali eles descrevem apenas intervalos fechados. Interval union é definido como um conjunto de intervalos fechados, disjuntos entre si, e apenas os limites dos intervalos extremos podem ser ±∞
    • Seria possível suportar essa notação, mas o código ficaria bem mais complexo. Por isso decidi bem cedo não dar suporte a isso. Ainda assim, poderia ser um recurso legal
    • Também fiquei um pouco confuso nessa parte. A notação padrão que eu conhecia usava parênteses, embora eu imagine que em ambientes ASCII isso talvez não funcione tão bem
  • Muito legal. Não entendi completamente todas as operações, mas mesmo o que entendi já foi bastante impressionante. Fico pensando que gostaria de ter conhecido aritmética sobre intervalos mais cedo nas aulas. Já aparecem conceitos parecidos em coisas como intervalos de confiança em estatística básica ou o ± das equações quadráticas, mas sempre achei meio frustrante não poder continuar calculando com o resultado como se fosse um único dado, tendo de tratar os dois valores do ± separadamente toda vez. Claro, entendo por que o professor quer voltar logo às aplicações e não se aprofundar nisso. Ainda assim, teria sido bom ao menos receber a dica de que esse tipo de objeto também admite aritmética geral. O que você mostrou vai muito além disso, mas a ideia de ver intervalos como dados com comportamento próprio parece uma validação dessa intuição
  • Às vezes penso que gostaria de ter conhecido interval arithmetic quando comecei a usar a biblioteca de intervalos de tempo tick em Clojure. Ela também inclui uma implementação de Allen's Interval Algebra e incorporou o conceito de conjuntos discretos de intervalos, útil em cálculos do mundo real. Por exemplo, combina bem com trabalho de RH para calcular conjuntos de intervalos de férias que pertencem a um certo ano. Eu só conhecia o trabalho de Allen e acabei descobrindo meio por acaso as vantagens que esses conjuntos trazem. O código está em juxt/tick
  • Consigo ver bastante utilidade nesta ferramenta, mas pessoalmente acho que uma calculadora probabilística seria ainda mais útil. Por exemplo, um resultado como 1 / [-1, 2] não diz quão plausíveis são os diferentes valores, e mesmo assumindo entradas uniformes, a saída claramente não parece seguir uma distribuição uniforme
  • Também implementei algo parecido recentemente, mas com foco em pertencimento a conjuntos. Por isso, para fazer uma análise booleana completa de interval membership, eu precisava da operação de complemento. Como os intervalos aqui são todos conjuntos fechados, o complemento vira um intervalo aberto; mas, no meu caso, não importava se os extremos estavam incluídos ou não, então eu não distingui intervalos abertos de fechados. Além disso, em arithmetic inexata, talvez nem faça muito sentido dizer de forma bem definida se um conjunto é aberto ou fechado
  • Estender a lógica para union of intervals parece muito interessante, mas fico curioso sobre a complexidade. Se uma única operação puder produzir dois intervalos, então em N operações pode haver, no pior caso, um crescimento exponencial. Aí isso talvez fique inviável para usos comuns, como abstract interpretation, a menos que se introduza aproximação depois de um certo número de intervalos
    • Sim, esse é um ponto correto, e esse problema é bem conhecido em abstract interpretation. Como você disse, normalmente se coloca um limite no tamanho do objeto e, quando esse limite é ultrapassado, os intervalos são fundidos. Dito isso, pelo menos em abstract interpretation, me parece que muitas vezes também se usam domínios mais refinados do que intervalos