หากคุณกำลังมองหาข้อผิดพลาดในการปัดเศษคุณไม่จำเป็นต้องมีห้องสมุดที่มีความแม่นยำสูง คุณสามารถใช้การวิเคราะห์ข้อผิดพลาดแทน
ฉันไม่สามารถหาข้อมูลอ้างอิงออนไลน์ได้ดี แต่ทั้งหมดอธิบายไว้ในมาตรา 3.3 ของหนังสือของ Nick Higham "ความแม่นยำและความเสถียรของอัลกอริธึมเชิงตัวเลข" ความคิดนั้นค่อนข้างง่าย:
- ใส่รหัสของคุณอีกครั้งเพื่อให้คุณมีการมอบหมายการดำเนินการทางคณิตศาสตร์เพียงครั้งเดียวในแต่ละบรรทัด
- สำหรับตัวแปรแต่ละตัวเช่น
x
สร้างตัวแปรx_err
ที่กำหนดค่าเริ่มต้นเป็นศูนย์เมื่อx
กำหนดค่าคงที่
- สำหรับการดำเนินงานในแต่ละเช่น
z = x * y
อัปเดตตัวแปรz_err
โดยใช้รูปแบบมาตรฐานของการลอยเลขคณิตจุดและส่งผลให้เกิดz
ความผิดพลาดและการเรียกใช้และx_err
y_err
- ค่าที่ส่งคืนของฟังก์ชันของคุณควรมี
_err
ค่าที่เกี่ยวข้องแนบมาด้วย นี่เป็นข้อมูลที่ถูกผูกไว้กับข้อผิดพลาด roundoff โดยรวมของคุณ
ส่วนที่ยุ่งยากคือขั้นตอนที่ 3 สำหรับการดำเนินการทางคณิตศาสตร์ที่ง่ายที่สุดคุณสามารถใช้กฎต่อไปนี้:
z = x + y
-> z_err = u*abs(z) + x_err + y_err
z = x - y
-> z_err = u*abs(z) + x_err + y_err
z = x * y
-> z_err = u*abs(z) + x_err*abs(y) + y_err*abs(x)
z = x / y
-> z_err = u*abs(z) + (x_err*abs(y) + y_err*abs(x))/y^2
z = sqrt(x)
-> z_err = u*abs(z) + x_err/(2*abs(z))
ที่u = eps/2
เป็น roundoff หน่วย ใช่กฎสำหรับ+
และ-
เหมือนกัน กฎสำหรับการดำเนินงานอื่น ๆ ที่สามารถสกัดได้อย่างง่ายดายโดยใช้การขยายตัวของซีรีส์เทย์เลอร์ของผลที่ได้นำไปใช้op(x)
op(x + x_err)
หรือคุณสามารถลองใช้ Google หรือใช้หนังสือของ Nick Higham
ยกตัวอย่างเช่นพิจารณา Matlab / Octave code ต่อไปนี้ซึ่งประเมินพหุนามในค่าสัมประสิทธิ์a
ณ จุดที่x
ใช้รูปแบบ Horner:
function s = horner ( a , x )
s = a(end);
for k=length(a)-1:-1:1
s = a(k) + x*s;
end
สำหรับขั้นตอนแรกเราแยกการดำเนินการทั้งสองในs = a(k) + x*s
:
function s = horner ( a , x )
s = a(end);
for k=length(a)-1:-1:1
z = x*s;
s = a(k) + z;
end
จากนั้นเราจะแนะนำ_err
ตัวแปร โปรดทราบว่าอินพุตa
และx
สันนิษฐานว่าเป็นที่แน่นอน แต่เราสามารถกำหนดให้ผู้ใช้ส่งค่าที่สอดคล้องกันสำหรับa_err
และx_err
:
function [ s , s_err ] = horner ( a , x )
s = a(end);
s_err = 0;
for k=length(a)-1:-1:1
z = x*s;
z_err = ...;
s = a(k) + z;
s_err = ...;
end
สุดท้ายเราใช้กฎที่อธิบายไว้ข้างต้นเพื่อรับข้อกำหนดข้อผิดพลาด:
function [ s , s_err ] = horner ( a , x )
u = eps/2;
s = a(end);
s_err = 0;
for k=length(a)-1:-1:1
z = x*s;
z_err = u*abs(z) + s_err*abs(x);
s = a(k) + z;
s_err = u*abs(s) + z_err;
end
โปรดทราบว่าเนื่องจากเราไม่มีa_err
หรือx_err
เช่นพวกเขาถือว่าเป็นศูนย์ข้อกำหนดที่เกี่ยวข้องจะถูกละเว้นเพียงในการแสดงออกข้อผิดพลาด
และอื่น ๆ ! ตอนนี้เรามีรูปแบบของฮอร์เนอร์ซึ่งส่งกลับค่าประมาณการข้อผิดพลาดขึ้นอยู่กับข้อมูล (หมายเหตุ: นี่คือขอบเขตบนของข้อผิดพลาด) พร้อมกับผลลัพธ์
ในฐานะที่เป็นบันทึกด้านข้างเนื่องจากคุณใช้ C ++ คุณอาจลองสร้างคลาสของคุณเองสำหรับค่าเลขทศนิยมซึ่งมีผลกับ_err
คำศัพท์และดำเนินการทางคณิตศาสตร์มากเกินไปเพื่ออัปเดตค่าเหล่านี้ตามที่อธิบายไว้ข้างต้น สำหรับรหัสขนาดใหญ่นี่อาจเป็นเส้นทางที่ง่ายขึ้นแม้ว่าจะมีประสิทธิภาพน้อยกว่าในการคำนวณ ต้องบอกว่าคุณอาจจะสามารถหาชั้นเรียนออนไลน์ได้ การค้นหาโดย Google อย่างรวดเร็วทำให้ฉันลิงก์นี้
± ux ( 1 ± u )