Saya pikir Akurasi dan Stabilitas Algoritma Numerik Higham membahas bagaimana orang dapat menganalisis jenis masalah ini. Lihat Bab 2, terutama latihan 2.8.
Dalam jawaban ini saya ingin menunjukkan sesuatu yang tidak benar-benar dibahas dalam buku Higham (sepertinya tidak terlalu dikenal luas, dalam hal ini). Jika Anda tertarik untuk membuktikan properti dari algoritma numerik sederhana seperti ini, Anda dapat menggunakan kekuatan pemecah SMT modern ( Satisfiability Modulo Theories ), seperti z3 , menggunakan paket seperti sbv di Haskell. Ini agak lebih mudah daripada menggunakan pensil dan kertas.
Misalkan saya diberi nilai , dan saya ingin tahu apakah z = ( x + y ) / 2 memenuhi x ≤ z ≤ y . Berikut kode 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
akan membiarkan saya melakukan ini secara otomatis . Berikut test1 fun
adalah proposisi bahwa untuk semua pelampung terbatas x , y dengan 0 ≤ x ≤ y .x ≤ f u n ( x , y) ≤ yx , y0 ≤ x ≤ y
λ> prove $ test1 (\x y -> (x + y) / 2)
Falsifiable. Counter-example:
x = 2.3089316e36 :: Float
y = 3.379786e38 :: Float
Itu meluap. Misalkan saya sekarang mengambil formula Anda yang lain: 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
Tidak berfungsi (karena underflow bertahap: , yang mungkin tidak intuitif karena semua aritmatika menjadi basis-2).( x / 2 ) × 2 ≠ x
Sekarang coba :z= x + ( y- x ) / 2
λ> prove $ test1 (\x y -> x + (y-x)/2)
Q.E.D.
Bekerja! Ini Q.E.D.
adalah bukti bahwa test1
properti berlaku untuk semua pelampung seperti yang didefinisikan di atas.
Bagaimana dengan yang sama, tetapi terbatas pada (bukan 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
Oke, jadi jika meluap, bagaimana dengan 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.
Jadi sepertinya di antara rumus yang saya coba di sini, tampaknya berfungsi (dengan bukti juga). Pendekatan SMT solver bagi saya merupakan cara yang jauh lebih cepat untuk menjawab kecurigaan tentang rumus titik-mengambang sederhana daripada melalui analisis kesalahan titik-mengambang dengan pensil dan kertas.x + ( y/ 2-x / 2)
Akhirnya, tujuan akurasi dan stabilitas seringkali bertentangan dengan tujuan kinerja. Untuk kinerja, saya tidak benar-benar melihat bagaimana Anda dapat melakukan lebih baik daripada , terutama karena kompiler masih akan melakukan tugas berat menerjemahkan ini menjadi instruksi mesin untuk Anda.( x + y) / 2
x ≤ x + ( y/ 2-x / 2)≤ySFloat
SDouble
-ffast-math
( x + y) / 2
PPPS Saya terbawa sedikit melihat hanya pada ekspresi aljabar sederhana tanpa persyaratan. Don Hatch 's rumus secara ketat baik.