Penso que a precisão e a estabilidade dos algoritmos numéricos de Higham abordam como se pode analisar esses tipos de problemas. Veja o Capítulo 2, especialmente o exercício 2.8.
Nesta resposta, gostaria de salientar algo que não é realmente abordado no livro de Higham (não parece ser muito conhecido, por falar nisso). Se você estiver interessado em provar propriedades de algoritmos numéricos simples como esses, poderá usar o poder dos modernos solucionadores de SMT ( Teorias do Módulo de Satisfação ), como o z3 , usando um pacote como o sbv em Haskell. Isso é um pouco mais fácil do que usar lápis e papel.
Suponha que me seja dado e gostaria de saber se z = ( x + y ) / 2 satisfaz x ≤ z ≤ y . O seguinte código Haskell0≤x≤yz=(x+y)/2x≤z≤y
import Data.SBV
test1 :: (SFloat -> SFloat -> SFloat) -> Symbolic SBool
test1 fun =
do [x, y] <- sFloats ["x", "y"]
constrain $ bnot (isInfiniteFP x) &&& bnot (isInfiniteFP y)
constrain $ 0 .<= x &&& x .<= y
let z = fun x y
return $ x .<= z &&& z .<= y
test2 :: (SFloat -> SFloat -> SFloat) -> Symbolic SBool
test2 fun =
do [x, y] <- sFloats ["x", "y"]
constrain $ bnot (isInfiniteFP x) &&& bnot (isInfiniteFP y)
constrain $ x .<= y
let z = fun x y
return $ x .<= z &&& z .<= y
vai me deixar fazer isso automaticamente . Aqui test1 fun
está a proposição de que para todos os flutuadores finitos x , y com 0 ≤ x ≤ y .x≤fun(x,y)≤yx,y0≤x≤y
λ> prove $ test1 (\x y -> (x + y) / 2)
Falsifiable. Counter-example:
x = 2.3089316e36 :: Float
y = 3.379786e38 :: Float
Transborda. Suponha que agora eu use sua outra fórmula: z=x/2+y/2
λ> prove $ test1 (\x y -> x/2 + y/2)
Falsifiable. Counter-example:
x = 2.3509886e-38 :: Float
y = 2.3509886e-38 :: Float
Não funciona (devido a underflow gradual: , que pode ser unintuitive devido a toda base-2 estar aritmética).( x / 2 ) × 2 ≠ x
Agora tente :z= x + ( y- x ) / 2
λ> prove $ test1 (\x y -> x + (y-x)/2)
Q.E.D.
Trabalho! A Q.E.D.
é uma prova de que a test1
propriedade possui para todos os carros alegóricos, conforme definido acima.
E o mesmo, mas restrito a (em vez de 0 ≤ x ≤ y )?x ≤ y0 ≤ x ≤ y
λ> prove $ test2 (\x y -> x + (y-x)/2)
Falsifiable. Counter-example:
x = -3.1300826e34 :: Float
y = 3.402721e38 :: Float
Ok, então, se estourar, que tal z = x + ( y / 2 - x / 2 ) ?y- xz= x + ( y/ 2-x / 2)
λ> prove $ test2 (\x y -> x + (y/2 - x/2))
Q.E.D.
x + ( y/ 2-x / 2)
( x + y) / 2
x ≤ x + ( y/ 2-x / 2)≤ySFloat
SDouble
-ffast-math
( x + y) / 2
PPPS Eu me empolguei um pouco olhando apenas para expressões algébricas simples, sem condicionais. A fórmula de Don Hatch é estritamente melhor.