หากคุณกำลังมองหาข้อผิดพลาดในการปัดเศษคุณไม่จำเป็นต้องมีห้องสมุดที่มีความแม่นยำสูง คุณสามารถใช้การวิเคราะห์ข้อผิดพลาดแทน
ฉันไม่สามารถหาข้อมูลอ้างอิงออนไลน์ได้ดี แต่ทั้งหมดอธิบายไว้ในมาตรา 3.3 ของหนังสือของ Nick Higham "ความแม่นยำและความเสถียรของอัลกอริธึมเชิงตัวเลข" ความคิดนั้นค่อนข้างง่าย:
- ใส่รหัสของคุณอีกครั้งเพื่อให้คุณมีการมอบหมายการดำเนินการทางคณิตศาสตร์เพียงครั้งเดียวในแต่ละบรรทัด
- สำหรับตัวแปรแต่ละตัวเช่น
xสร้างตัวแปรx_errที่กำหนดค่าเริ่มต้นเป็นศูนย์เมื่อxกำหนดค่าคงที่
- สำหรับการดำเนินงานในแต่ละเช่น
z = x * yอัปเดตตัวแปรz_errโดยใช้รูปแบบมาตรฐานของการลอยเลขคณิตจุดและส่งผลให้เกิดzความผิดพลาดและการเรียกใช้และx_erry_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 )