Я думаю, что Точность и Стабильность Численных Алгоритмов Хайама рассматривают, как можно проанализировать эти типы проблем. Смотрите Главу 2, особенно упражнение 2.8.
В этом ответе я хотел бы указать на то, что на самом деле не рассматривается в книге Хайама (в этом отношении она не очень широко известна). Если вы заинтересованы в проверке свойств простых численных алгоритмов, таких как эти, вы можете использовать возможности современных SMT-решателей ( Satisfiability Modulo Theories ), таких как z3 , используя пакет, такой как sbv в Haskell. Это несколько проще, чем с помощью карандаша и бумаги.
Предположим, мне дали , и я хотел бы знать, удовлетворяет ли z = ( x + y ) / 2 x ≤ z ≤ y . Следующий код на 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
позволит мне сделать это автоматически . Вот test1 fun
это предположение , что для всех конечных поплавками х , у с 0 ≤ х ≤ у .x≤fun(x,y)≤yх , у0 ≤ х ≤ у
λ> prove $ test1 (\x y -> (x + y) / 2)
Falsifiable. Counter-example:
x = 2.3089316e36 :: Float
y = 3.379786e38 :: Float
Это переполняет. Предположим, теперь я беру другую формулу: Z= х / 2 + у/ 2
λ> prove $ test1 (\x y -> x/2 + y/2)
Falsifiable. Counter-example:
x = 2.3509886e-38 :: Float
y = 2.3509886e-38 :: Float
Не работает (из - за постепенную потерю значимости: , которые могут быть неинтуитивными из - за все арифметическое существом с основанием 2).( x / 2 ) × 2 ≠ x
Теперь попробуйте :Z= х + ( у- х ) / 2
λ> prove $ test1 (\x y -> x + (y-x)/2)
Q.E.D.
Работает! Q.E.D.
Является доказательством того, что test1
свойство выполняется для всех поплавков , как определено выше.
Как насчет того же, но ограниченного (вместо 0 ≤ x ≤ y )?х ≤ у0 ≤ х ≤ у
λ> prove $ test2 (\x y -> x + (y-x)/2)
Falsifiable. Counter-example:
x = -3.1300826e34 :: Float
y = 3.402721e38 :: Float
Итак, если переполняется, как насчет z = х + ( у / 2 - х / 2 ) ?Y- хZ= х + ( у/ 2-х / 2)
λ> prove $ test2 (\x y -> x + (y/2 - x/2))
Q.E.D.
Таким образом, кажется, что среди формул, которые я здесь пробовал, кажется, работает (с доказательством тоже). Метод решения SMT кажется мне гораздо более быстрым способом ответа на подозрения относительно простых формул с плавающей точкой, чем анализ ошибок с плавающей точкой карандашом и бумагой.х + ( у/ 2-х / 2)
Наконец, цель точности и стабильности часто расходится с целью производительности. Что касается производительности, я не очень понимаю, как вы можете сделать лучше, чем , тем более что компилятор все равно будет выполнять тяжелую работу по переводу этого в машинные инструкции для вас.( х + у) / 2
х ≤ х + ( у/ 2-х / 2)≤уSFloat
SDouble
-ffast-math
( х + у) / 2
PPPS Я немного увлекся, глядя только на простые алгебраические выражения без условий. Дон Hatch «s формула строго лучше.