อะไรทำให้เกิดข้อผิดพลาดในการปัดเศษทศนิยม


62

ฉันรู้ว่าเลขทศนิยมมีปัญหาความแม่นยำ ฉันมักจะเอาชนะพวกเขาโดยการเปลี่ยนไปใช้การแทนทศนิยมคงที่ของตัวเลขหรือเพียงแค่ละเลยข้อผิดพลาด

อย่างไรก็ตามฉันไม่ทราบว่าอะไรคือสาเหตุของความไม่ถูกต้องนี้ เหตุใดจึงมีปัญหาการปัดเศษจำนวนมากด้วยตัวเลขลอย


28
เพื่อความแม่นยำไม่ใช่ข้อผิดพลาดที่เกิดจากการปัดเศษที่คนส่วนใหญ่กังวล - เป็นความจริงที่ว่าการปัดเศษจุดลอยตัวแบบไบนารีทำงานในลักษณะที่ไม่คุ้นเคย การสลับไปใช้การแทนค่าทศนิยมสามารถทำให้การปัดเศษเป็นไปได้ง่ายขึ้น แต่ในการแลกเปลี่ยนคุณจะเพิ่มข้อผิดพลาดสัมพัทธ์เกือบตลอดเวลา(หรือต้องเพิ่มพื้นที่เก็บข้อมูลเพื่อชดเชย)
Daniel Pryden

12
ความพยายามของฉันในการกำจัดความสับสนที่พบบ่อยที่สุด: floating-point-gui.de
Michael Borgwardt

ผมคิดว่าสิ่งที่ @DanielPryden หมายถึงคือ"เปลี่ยนเป็น [จุดคงที่] ตัวแทนสามารถทำให้ประพฤติปัดเศษในทางที่ง่ายขึ้น ..." สิ่งที่ทำให้เกิดปัญหาการปัดเศษไม่ว่าจะเป็นตัวเลขตายตัวหรือตัวเลขทศนิยมคือความกว้างของคำ จำกัด เพียงแค่มีจุดลอยตัวขนาดของข้อผิดพลาดในการปัดเศษตามปกติจะยังคงสัดส่วนกับขนาดของจำนวนที่ถูกปัดเศษ (ยกเว้นเมื่อคุณมีขนาดเล็กมากและเป็นตัวเลข "ปกติ")
robert bristow-johnson

@robert: นั่นไม่ใช่สิ่งที่ฉันหมายถึง "ข้อผิดพลาด" ที่คนส่วนใหญ่พบกับจุดลอยตัวนั้นไม่เกี่ยวอะไรกับจุดลอยตัวต่อมันเป็นฐาน IEEE-754 ลอยและเป็นสองเท่าใช้เลขชี้กำลังในฐาน 2 ซึ่งหมายความว่าตัวเลขเศษส่วนปัดเศษเป็นกำลังลบสอง (1/2, 1/16, 1/1024 ฯลฯ ) แทนที่จะใช้กำลังลบ 10 (1 / 10, 1/1000 ฯลฯ ) สิ่งนี้นำไปสู่ผลลัพธ์ที่ไม่เข้าใจง่ายเช่นการปัดเศษ 0.1 ถึง 0.1000001 และปัญหาที่คล้ายกัน
Daniel Pryden

คุณสามารถทำตัวเลขทศนิยมในฐาน 10 - นั่นคือวิธีการdecimalทำงานของ. NET จุดคงที่ในทางกลับกันจะแตกต่างกัน ตราบใดที่ขอบเขตของคุณมี จำกัด จุดคงที่คือคำตอบที่ดี แต่ช่วงของข้อ จำกัด ทำให้จุดคงที่ไม่เหมาะสมสำหรับแอปพลิเคชันทางคณิตศาสตร์จำนวนมากและการใช้งานของหมายเลขจุดคงที่นั้นมักไม่ได้รับการปรับให้เหมาะสมในฮาร์ดแวร์เป็นผล
Daniel Pryden

คำตอบ:


82

นี่เป็นเพราะเศษส่วนบางส่วนต้องการจำนวนที่มาก (หรือไม่ จำกัด ) ที่จะแสดงโดยไม่ต้องปัดเศษ นี่ถือเป็นจริงสำหรับสัญลักษณ์ทศนิยมเท่าสำหรับไบนารีหรืออื่น ๆ หากคุณจะ จำกัด จำนวนตำแหน่งทศนิยมที่จะใช้สำหรับการคำนวณของคุณ (และหลีกเลี่ยงการคำนวณในรูปแบบเศษส่วน) คุณจะต้องปัดเศษแม้แต่การแสดงออกง่าย ๆ เป็น 1/3 + 1/3 แทนที่จะเขียน 2/3 ดังนั้นคุณจะต้องเขียน 0.33333 + 0.33333 = 0.66666 ซึ่งไม่เหมือนกับ 2/3

ในกรณีที่คอมพิวเตอร์มีจำนวนตัวเลข จำกัด ตามลักษณะทางเทคนิคของหน่วยความจำและการลงทะเบียน CPU สัญกรณ์ไบนารีที่ใช้ภายในเพิ่มความยากลำบากมากขึ้น ปกติคอมพิวเตอร์จะไม่สามารถแสดงตัวเลขในรูปของเศษส่วนได้แม้ว่าภาษาการเขียนโปรแกรมบางภาษาจะเพิ่มความสามารถนี้ซึ่งทำให้ปัญหาเหล่านั้นสามารถหลีกเลี่ยงได้ในระดับหนึ่ง

สิ่งที่นักวิทยาศาสตร์คอมพิวเตอร์ทุกคนควรรู้เกี่ยวกับเลขคณิตทศนิยม


12
จับได้เห็นชัดตรงเผง. แต่ฉันก็จะทราบด้วยว่าตัวเลขบางตัวที่ลงท้ายด้วยทศนิยมไม่ได้จบลงด้วยเลขฐานสอง โดยเฉพาะอย่างยิ่ง 0.1 เป็นจำนวนที่เกิดซ้ำในเลขฐานสองดังนั้นจึงไม่มีเลขฐานสองจุดลอยตัวที่สามารถแทน 0.1 ได้อย่างแน่นอน
Jack Aidley

4
คะแนนลอยตัวไม่เพียงมีประโยชน์สำหรับตำแหน่งทศนิยมจำนวนมาก จำนวนเต็ม 32 บิตสามารถนับได้ถึงประมาณ 4 พันล้านเท่านั้น แต่การลอยแบบ 32 บิตนั้นมีขนาดใหญ่เกือบจะไม่ จำกัด
Abhi Beckert

7
โดยเฉพาะอย่างยิ่งเศษส่วนที่เราสามารถแสดงเป็นทศนิยมที่แน่นอนนั้นเป็นตัวประกอบที่ตัวประกอบส่วนของตัวส่วนประกอบด้วย 2 และ 5 เท่านั้น (เช่นเราสามารถแสดง 3/10 และ 7/25 แต่ไม่ใช่ 11/18) เมื่อเราย้ายไปที่ไบนารี่เราจะสูญเสียตัวประกอบ 5 เพื่อให้สามารถแสดงค่าเฉพาะไดอะดิค (เช่น 1/4, 3/128) เท่านั้น
เดวิดจางจาง

70

ในขั้นต้นข้อผิดพลาดในการปัดเศษมาจากข้อเท็จจริงที่ว่าอนันต์ของจำนวนจริงทั้งหมดไม่สามารถถูกแทนด้วยหน่วยความจำอัน จำกัด ของคอมพิวเตอร์ทำให้หน่วยความจำเล็ก ๆ เพียงชิ้นเดียวเช่นตัวแปรจุดลอยตัวเดียวดังนั้นตัวเลขจำนวนมากจึงเป็นเพียงการประมาณ จำนวนที่หมายถึงการเป็นตัวแทน

เนื่องจากมีเพียงจำนวน จำกัด ของค่าซึ่งไม่ใช่การประมาณและการดำเนินการใด ๆ ระหว่างการประมาณและอีกจำนวนหนึ่งทำให้เกิดการประมาณดังนั้นข้อผิดพลาดในการปัดเศษจึงแทบจะหลีกเลี่ยงไม่ได้

สิ่งที่สำคัญคือการตระหนักถึงเมื่อพวกเขามีแนวโน้มที่จะก่อให้เกิดปัญหาและดำเนินการเพื่อลดความเสี่ยง


นอกเหนือไปจากเดวิดโกลด์เบิร์ก 's จำเป็นอะไรทุกวิทยาศาสตร์คอมพิวเตอร์ควรทราบเกี่ยวกับจุดลอยเลขคณิต (อีกครั้งตีพิมพ์โดย Sun / ออราเคิลเป็นภาคผนวกของพวกเขาตัวเลขการคำนวณคู่มือ ) ซึ่งได้รับการกล่าวถึงโดยThorstenที่ACCUวารสารเกินวิ่งที่ดีเยี่ยม ชุดของบทความโดยริชาร์ดแฮร์ริสเกี่ยวกับบลูส์ Floating Point

ชุดเริ่มต้นด้วย

การคำนวณเชิงตัวเลขมีข้อผิดพลาดมากมาย Richard Harris เริ่มมองหากระสุนเงิน

มังกรที่มีตัวเลขผิดพลาดนั้นไม่ได้ถูกปลุกให้ตื่นขึ้นจากการนอนหลับของเขา แต่หากเข้าหาอย่างไม่ระมัดระวังเขาจะทำดาเมจเป็นครั้งคราวอย่างรุนแรงต่อการคำนวณของโปรแกรมเมอร์ที่ไม่ระวัง

มากเสียจนโปรแกรมเมอร์บางคนเมื่อเขาอยู่ในป่าเลขคณิตเลขทศนิยมของ IEEE 754 ให้คำแนะนำแก่พวกเขาในการเดินทางในดินแดนที่ยุติธรรม

ในบทความชุดนี้เราจะสำรวจโลกของการคำนวณเชิงตัวเลขโดยเปรียบเทียบความแตกต่างของเลขคณิตจุดลอยตัวกับเทคนิคบางอย่างที่ได้รับการเสนอว่าเป็นการแทนที่ที่ปลอดภัยกว่าสำหรับมัน เราจะได้เรียนรู้ว่าดินแดนของมังกรนั้นมาถึงแล้วและโดยทั่วไปเราต้องเหยียบอย่างระมัดระวังหากเรากลัวความสนใจของเขา

Richard เริ่มต้นด้วยการอธิบายอนุกรมวิธานของจำนวนจริง, เหตุผล, ไม่มีเหตุผล, พีชคณิตและยอดเยี่ยม จากนั้นเขาจะอธิบายการแทน IEEE754 ก่อนที่จะเกิดข้อผิดพลาดในการยกเลิกและลำดับของปัญหาการดำเนินการ

หากคุณอ่านไม่ลึกไปกว่านี้คุณจะมีพื้นฐานที่ยอดเยี่ยมในปัญหาที่เกี่ยวข้องกับตัวเลขจุดลอยตัว

หากคุณต้องการทราบข้อมูลเพิ่มเติมเขาก็ดำเนินการต่อไป

จากนั้นเขาเปลี่ยนไปพยายามช่วยคุณรักษาแคลคูลัสบลูส์ของคุณ

และสุดท้าย แต่ไม่ท้ายสุดนั่นก็คือ

ทั้งชุดของบทความเป็นอย่างดีมูลค่ามองและที่ 66 หน้ารวมพวกเขายังคงมีขนาดเล็กกว่า 77 หน้าของกระดาษโกลด์เบิร์ก

ในขณะที่ชุดนี้ครอบคลุมมากจากพื้นดินเดียวกันผมพบว่ามันค่อนข้างเข้าถึงได้มากขึ้นกว่าโกลด์เบิร์กกระดาษ ฉันพบว่ามันง่ายกว่าที่จะเข้าใจส่วนที่ซับซ้อนของกระดาษหลังจากอ่านบทความ Richards ก่อนหน้านี้และหลังจากบทความก่อนหน้านั้น Richard ได้แยกออกเป็นส่วนที่น่าสนใจมากมายที่ไม่ได้สัมผัสกับกระดาษ Goldberg


ในฐานะที่เป็นAK ตรัสดังกล่าวไว้ในความคิดเห็น:

ในฐานะที่เป็นผู้เขียนบทความที่ผมอยากจะบอกว่าผมได้สร้างรุ่นโต้ตอบของพวกเขาในบล็อกของฉันwww.thusspakeak.comเริ่มต้นด้วยthusspakeak.com/ak/2013/06


1
ในฐานะที่เป็นผู้เขียนบทความที่ผมอยากจะบอกว่าผมได้สร้างรุ่นโต้ตอบของพวกเขาในบล็อกของฉัน www.thusspakeak.com เริ่มต้นด้วยthusspakeak.com/ak/2013/06
ดังนั้นจึงพูด ak

ขอบคุณ @ thusspakea.k ฉันได้เพิ่มหมายเหตุลงในคำตอบของฉันและองค์ประกอบแบบโต้ตอบเหล่านั้นทำงานได้ดีมาก
Mark Booth

12

ดีThorstenมีชัดเจนเชื่อมโยง ฉันจะเพิ่ม:

รูปแบบใด ๆ ของการเป็นตัวแทนจะมีข้อผิดพลาดในการปัดเศษจำนวนหนึ่ง ลองแสดง 1/3 ในทศนิยมของ IEEE หรือเป็นทศนิยม ไม่สามารถทำได้อย่างถูกต้อง สิ่งนี้เกินกว่าจะตอบคำถามของคุณได้ แต่ฉันได้ใช้กฏเกณฑ์นี้สำเร็จแล้ว:

  • จัดเก็บค่าที่ผู้ใช้ป้อนในรูปแบบทศนิยม (เพราะพวกเขาเกือบจะป้อนเป็นทศนิยมแทน - ผู้ใช้น้อยมากจะใช้ไบนารีหรือฐานสิบหก) ด้วยวิธีนี้คุณจะมีตัวแทนที่ผู้ใช้ป้อนจริง ๆ เสมอ
  • หากคุณต้องเก็บเศษส่วนที่ผู้ใช้ป้อนให้เก็บเศษและส่วน (เป็นทศนิยม)
  • หากคุณมีระบบที่มีหน่วยวัดหลายหน่วยสำหรับปริมาณเท่ากัน (เช่นเซลเซียส / ฟาเรนไฮต์) และผู้ใช้สามารถป้อนได้ทั้งคู่ให้เก็บค่าที่ป้อนและหน่วยที่ป้อนเข้าไปอย่าพยายามแปลงและบันทึกเป็น การแสดงเดี่ยวเว้นแต่ว่าคุณสามารถทำได้โดยไม่สูญเสียความแม่นยำ / ความแม่นยำ ใช้ค่าที่เก็บไว้และหน่วยในการคำนวณทั้งหมด
  • จัดเก็บค่าสร้างเครื่องในจุดลอยตัว IEEE (ซึ่งอาจเป็นตัวเลขที่สร้างขึ้นโดยอุปกรณ์ตรวจวัดทางอิเล็กทรอนิกส์เช่นเซ็นเซอร์อะนาล็อกที่มีตัวแปลง A / D หรือผลลัพธ์ที่ไม่มีการคำนวณรอบ) โปรดทราบว่านี่ไม่สามารถใช้งานได้หากคุณอ่านเซ็นเซอร์ผ่านการเชื่อมต่อแบบอนุกรมและมันให้ค่าในรูปแบบทศนิยม (เช่น 18.2 C)
  • จัดเก็บยอดรวมที่ผู้ใช้สามารถดูได้เป็นต้นเป็นทศนิยม (เช่นยอดคงเหลือในบัญชีธนาคาร) ปัดเศษอย่างเหมาะสม แต่ใช้ค่านั้นเป็นค่าที่ชัดเจนสำหรับการคำนวณในอนาคตทั้งหมด

ฉันจะเพิ่ม: ลองใช้ชุดคณิตศาสตร์ที่มีความแม่นยำตามอำเภอใจเช่น ARPREC หรือ decNumber
Blrfl

ฉันไม่ได้ทศนิยม (ตรงข้ามกับไบนารี) มีประโยชน์มากสำหรับค่าจำนวนเต็มเช่นตัวเศษและตัวส่วนของเศษส่วน ทั้งสามารถเก็บค่าจำนวนเต็มแน่นอนและไบนารีมีประสิทธิภาพมากขึ้น มีค่าใช้จ่ายในการแปลงไปมาสำหรับอินพุทและเอาท์พุท แต่ก็มีแนวโน้มที่จะถูกครอบงำด้วยค่าใช้จ่ายในการทำ I / O ทางกายภาพ
Keith Thompson

10

สิ่งที่ดูเหมือนจะยังไม่ได้รับการกล่าวถึงเพื่อให้ห่างไกลที่มีแนวความคิดของนั้นขั้นตอนวิธีการที่ไม่แน่นอนและปัญหาป่วยปรับอากาศ ฉันจะพูดกับอดีตคนแรกเนื่องจากดูเหมือนจะเป็นข้อผิดพลาดที่บ่อยขึ้นสำหรับนักคิดตัวเลขมือใหม่

พิจารณาคำนวณอำนาจของ (ซึ่งกันและกัน) อัตราส่วนทองคำที่φ=0.61803…; วิธีหนึ่งที่เป็นไปได้ที่จะไปเกี่ยวกับเรื่องนี้คือการใช้สูตรเรียกซ้ำตัวเองφ^n=φ^(n-2)-φ^(n-1)เริ่มต้นด้วยและφ^0=1 φ^1=φหากคุณเรียกใช้การสอบถามซ้ำครั้งนี้ในสภาพแวดล้อมการคำนวณที่คุณชื่นชอบและเปรียบเทียบผลลัพธ์กับพลังที่ได้รับการประเมินอย่างแม่นยำคุณจะพบว่าตัวเลขที่มีความสำคัญของการพังทลายช้า นี่คือสิ่งที่เกิดขึ้นเช่นในMathematica :

ph = N[1/GoldenRatio];  
Nest[Append[#1, #1[[-2]] - #1[[-1]]] & , {1, ph}, 50] - ph^Range[0, 51]  
{0., 0., 1.1102230246251565*^-16, -5.551115123125783*^-17, 2.220446049250313*^-16, 
-2.3592239273284576*^-16, 4.85722573273506*^-16, -7.147060721024445*^-16, 
1.2073675392798577*^-15, -1.916869440954372*^-15, 3.1259717037102064*^-15, 
-5.0411064211886014*^-15, 8.16837916750579*^-15, -1.3209051907825398*^-14, 
2.1377864756200182*^-14, -3.458669982359108*^-14, 5.596472721011714*^-14, 
-9.055131861349097*^-14, 1.465160458236081*^-13, -2.370673237795176*^-13, 
3.835834102607072*^-13, -6.206507137114341*^-13, 1.004234127360273*^-12, 
-1.6248848342954435*^-12, 2.6291189633497825*^-12, -4.254003796798193*^-12, 
6.883122762265558*^-12, -1.1137126558640235*^-11, 1.8020249321541067*^-11, 
-2.9157375879969544*^-11, 4.717762520172237*^-11, -7.633500108148015*^-11, 
1.23512626283229*^-10, -1.9984762736468268*^-10, 3.233602536479646*^-10, 
-5.232078810126407*^-10, 8.465681346606119*^-10, -1.3697760156732426*^-9, 
2.216344150333856*^-9, -3.5861201660070964*^-9, 5.802464316340953*^-9, 
-9.388584482348049*^-9, 1.5191048798689004*^-8, -2.457963328103705*^-8, 
3.9770682079726053*^-8, -6.43503153607631*^-8, 1.0412099744048916*^-7, 
-1.6847131280125227*^-7, 2.725923102417414*^-7, -4.4106362304299367*^-7, 
7.136559332847351*^-7, -1.1547195563277288*^-6}

ผลลัพธ์ที่อ้างว่าφ^41มีสัญญาณไม่ถูกต้องและก่อนหน้านี้ค่าที่คำนวณและเกิดขึ้นจริงสำหรับการφ^39แบ่งปันไม่มีตัวเลขเหมือนกัน ( 3.484899258054952* ^ - 9 for the computed version against the true value7.071019424062048 *^-9) ดังนั้นอัลกอริธึมจึงไม่เสถียรและไม่ควรใช้สูตรการเรียกซ้ำนี้ในการคำนวณแบบไม่แน่นอน นี่เป็นเพราะธรรมชาติโดยธรรมชาติของสูตรการเรียกซ้ำ: มีวิธี "การสลาย" และ "การเติบโต" สำหรับการเรียกซ้ำครั้งนี้และพยายามที่จะคำนวณวิธีการแก้ปัญหา "การสลาย" โดยวิธีการแก้ปัญหาข้างหน้าเมื่อมีทางเลือกอื่น สำหรับความเศร้าโศกเชิงตัวเลข ดังนั้นควรแน่ใจว่าอัลกอริธึมเชิงตัวเลขของเขา / เธอนั้นเสถียร

ถึงแนวคิดของปัญหาที่ไม่มีเงื่อนไข : แม้ว่าอาจมีวิธีที่มั่นคงในการทำบางสิ่งบางอย่างเป็นตัวเลขมันอาจเป็นไปได้ว่าปัญหาที่คุณเพิ่งแก้ไขไม่ได้ด้วยอัลกอริทึมของคุณ นี่เป็นความผิดพลาดของปัญหาไม่ใช่วิธีการแก้ปัญหา ตัวอย่างที่ยอมรับในเชิงตัวเลขคือคำตอบของสมการเชิงเส้นที่เกี่ยวข้องกับสิ่งที่เรียกว่า "ฮิลแบร์ตเมทริกซ์":

เมทริกซ์ของฮิลแบร์ต

เมทริกซ์เป็นตัวอย่างที่ยอมรับได้ของเมทริกซ์ที่ไม่ดี : การพยายามแก้ไขระบบที่มีเมทริกซ์ฮิลแบร์ตขนาดใหญ่อาจส่งคืนโซลูชันที่ไม่ถูกต้อง

นี่คือการสาธิตMathematica : เปรียบเทียบผลลัพธ์ของการคำนวณทางคณิตศาสตร์ที่แน่นอน

Table[LinearSolve[HilbertMatrix[n], HilbertMatrix[n].ConstantArray[1, n]], {n, 2, 12}]
{{1, 1}, {1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 
  1}, {1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1,
   1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 
  1, 1, 1, 1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}

และเลขคณิตไม่ถูกต้อง

Table[LinearSolve[N[HilbertMatrix[n]], N[HilbertMatrix[n].ConstantArray[1, n]]], {n, 2, 12}]
{{1., 1.}, {1., 1., 1.}, {1., 1., 1., 1.}, {1., 1., 1., 1., 1.},  
  {1., 1., 1., 1., 1., 1.}, {1., 1., 1., 1., 1., 1., 1.}, 
  {1., 1., 1., 1., 1., 1., 1., 1.}, {1., 1., 1., 1., 1., 1., 1., 1., 1.},  
  {1., 1., 1., 0.99997, 1.00014, 0.999618, 1.00062, 0.9994, 1.00031, 
  0.999931}, {1., 1., 0.999995, 1.00006, 0.999658, 1.00122, 0.997327, 
  1.00367, 0.996932, 1.00143, 0.999717}, {1., 1., 0.999986, 1.00022, 
  0.998241, 1.00831, 0.975462, 1.0466, 0.94311, 1.04312, 0.981529, 
  1.00342}}

(หากคุณลองใช้ในMathematicaคุณจะสังเกตเห็นข้อความแสดงข้อผิดพลาดสองสามข้อความเตือนว่าการปรากฏตัวไม่เหมาะสม)

ในทั้งสองกรณีการเพิ่มความแม่นยำเพียงอย่างเดียวนั้นไม่สามารถรักษาได้ มันจะชะลอการพังทลายของสิ่งที่หลีกเลี่ยงไม่ได้เท่านั้น

นี่คือสิ่งที่คุณอาจต้องเผชิญ วิธีแก้ปัญหาอาจเป็นเรื่องยาก: ในตอนแรกคุณอาจกลับไปที่กระดานวาดภาพหรือลุยวารสาร / หนังสือ / อะไรก็ได้ที่จะหาว่ามีใครมาแก้ปัญหาที่ดีกว่าคุณ สำหรับวินาทีคุณอาจยอมแพ้หรือปรับโครงสร้างปัญหาของคุณให้เป็นสิ่งที่ง่ายต่อการเข้าใจมากขึ้น


ฉันจะปล่อยให้คุณด้วยคำพูดจาก Dianne O'Leary:

ชีวิตอาจทำให้เรามีปัญหาที่ไม่มีเงื่อนไข แต่ไม่มีเหตุผลที่ดีที่จะจัดการกับอัลกอริทึมที่ไม่เสถียร


9

เนื่องจากฐานสิบฐานสิบไม่สามารถแสดงในฐาน 2 ได้

หรือในคำอื่น ๆ 1/10 ไม่สามารถเปลี่ยนเป็นเศษส่วนด้วยพลังของ 2 ในส่วน (ซึ่งเป็นสิ่งที่ตัวเลขจุดลอยตัวเป็นหลัก)


11
ไม่จริงอย่างแน่นอน: 0.5 และ 0.25 สามารถแสดงในฐาน 2 ได้ฉันคิดว่าคุณหมายถึง "ไม่ใช่เลขฐานสิบทั้งหมด"
Scott Whitlock

3
แม่นยำมากขึ้น ไม่สามารถแสดงตัวเลขเศษส่วนทั้งหมดได้อย่างแม่นยำโดยใช้เครื่องหมายจุดลอย (เช่นกับ. ทั้งฐาน 2 และฐาน 10 มีปัญหาตรงนี้) ลองทำ9*3.3333333ในรูปทศนิยมและมาที่9*3 1/3
Martin York

1
นี่คือแหล่งที่พบบ่อยที่สุดของความสับสนจุดลอย .1 + .1 != .2เนื่องจากการเข้ารหัสแบบเลขฐานสองทศนิยมถูกใช้ไม่ใช่ทศนิยม
Sean McMillan

@SeanMcMillan: และ1.0/3.0*3.0 != 1.0เนื่องจากมีการใช้การเข้ารหัสเลขฐานสองแบบ floating-point ไม่ใช่ trinary
Keith Thompson

8

ในวิชาคณิตศาสตร์มีจำนวนตรรกยะจำนวนมากมาย ตัวแปร 32 บิตสามารถมีค่าต่างกัน2 32เท่านั้นและตัวแปร 64 บิตมีเพียง 2 64ค่า ดังนั้นจึงมีจำนวนตรรกยะจำนวนมากที่ไม่มีตัวแทนที่แม่นยำ

เราสามารถคิดแผนการที่จะทำให้เราสามารถเป็นตัวแทนของ 1/3 ได้อย่างสมบูรณ์หรือ 1/100 ปรากฎว่าสำหรับวัตถุประสงค์ในทางปฏิบัติมากมายนี้ไม่ได้มีประโยชน์มาก มีข้อยกเว้นหนึ่งข้อใหญ่: ในด้านการเงินเศษส่วนทศนิยมมักปรากฏขึ้น นั่นเป็นเพราะส่วนใหญ่การเงินเป็นกิจกรรมของมนุษย์ไม่ใช่เรื่องทางกายภาพ

ดังนั้นเรามักจะเลือกใช้เลขทศนิยมแบบไบนารีและปัดค่าใด ๆ ที่ไม่สามารถแทนด้วยเลขฐานสองได้ แต่ในด้านการเงินบางครั้งเราเลือกทศนิยมทศนิยมและค่ารอบเป็นค่าทศนิยมที่ใกล้เคียงที่สุด


2
ยิ่งแย่กว่านั้นในขณะที่จำนวนหน่วยความจำที่ไม่มีที่สิ้นสุด (นับไม่ถ้วน) จะช่วยให้คนหนึ่งเป็นตัวแทนของปันส่วนทั้งหมดมันจะไม่พอเพียงสำหรับการเป็นตัวแทนของ reals ยิ่งกว่านั้นตัวเลขจริงทั้งหมดเกือบทั้งหมดยังไม่สามารถคำนวณได้ สิ่งที่ดีที่สุดที่เราสามารถทำได้กับจำนวนหน่วยความจำที่ จำกัด คือประมาณช่วงเซตย่อยของ reals
David Hammen

4
@ เควิน: คุณกำลังพูดถึงตัวเลขที่คำนวณได้ซึ่งเป็นเซตย่อยเล็ก ๆ (เซตย่อยที่มีค่าเป็นศูนย์) ของ reals
David Hammen

1
+1 สำหรับคำอธิบายพื้นฐานที่สุด: คุณกำลังพยายามแสดงจำนวนอนันต์ด้วยจำนวนบิตที่แน่นอน
Raku

1
@DavidHammen: ตัวเลขที่คำนวณได้เป็นเซตย่อยเล็ก ๆ (ของการวัดศูนย์) ของ reals - แต่ทุกหมายเลขที่คุณจะทำงานด้วยในโปรแกรมคือตามคำจำกัดความคำนวณได้
Keith Thompson

3
@Giorgio: ถ้าคุณเลือกเป็นตัวแทนขวา, รากที่สองของ 2 เป็น"√2"แทนได้เช่นเป็นสตริง (เครื่องคิดเลข HP-48 รุ่นเก่าของฉันสามารถทำสิ่งนั้นได้อย่างแน่นอนและการหาค่านั้นส่งผลให้เกิดขึ้น2.0จริง ๆ ) มีเพียงจำนวนอนันต์ที่นับได้ของจำนวนจริงที่เป็นตัวแทนสำหรับการแทน จำกัดใด ๆ - แต่ไม่มีการคำนวณใด ๆในหลักการเป็นตัวแทน ในทางปฏิบัติระบบเลขฐานสองแบบลอยตัว จำกัด อย่างรุนแรง จำกัด ชุดของตัวเลขที่สามารถแทนได้ด้วยประโยชน์ของความเร็วที่เห็นได้ชัดและการจัดเก็บข้อมูลขนาดเล็กเมื่อเทียบกับการเป็นตัวแทนสัญลักษณ์
Keith Thompson

-2

"ปัญหาการปัดเศษ" ที่ชัดเจนจริงๆเท่านั้นที่มีจำนวนจุดลอยตัวที่ฉันคิดว่าเป็นกับตัวกรองค่าเฉลี่ยเคลื่อนที่:

$$ \ start {align} y [n] & = \ frac {1} {N} \ sum \ limit_ {i = 0} ^ {N-1} x [ni] \ & = y [n-1] + \ frac {1} {N} (x [n] - x [nN]) \ \ end {align} $$

เพื่อให้งานนี้ปราศจากเสียงรบกวนคุณต้องการให้แน่ใจว่า $ x [n] $ ที่คุณเพิ่มในตัวอย่างปัจจุบันนั้นเหมือนกับ $ x [nN] $ คุณจะลบ $ N $ ตัวอย่างลงใน อนาคต. หากไม่เป็นเช่นนั้นสิ่งที่แตกต่างกันคือความวุ่นวายเล็กน้อยที่ติดอยู่ในสายการหน่วงเวลาของคุณและจะไม่ออกมา นั่นเป็นเพราะตัวกรองค่าเฉลี่ยเคลื่อนที่นี้ถูกสร้างขึ้นจริงด้วย IIR ที่มีขั้วเสถียรเล็กน้อยที่ $ z = 1 $ และศูนย์ที่ยกเลิกภายใน แต่เป็นผู้รวมและอึใด ๆ ที่รวมเข้าด้วยกันและไม่ถูกลบออกทั้งหมดจะมีอยู่ในผลรวมของผู้ผสานรวมตลอดไป นี่คือที่จุดคงที่ไม่มีปัญหาเดียวกันกับที่ตัวเลขจุดลอยตัวทำ


เฮ้ไม่ได้มาร์กอัป $ LaTeX $ math ทำงานในฟอรัม prog.SE ??? มันง่อยจริง ๆ ถ้าไม่
robert bristow-johnson

1
ดูสิ่งนี้บน meta.SOและคำถามที่เชื่อมโยง
AakashM
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.