การคำนวณที่แข็งแกร่งของค่าเฉลี่ยของตัวเลขสองตัวในจำนวนทศนิยม?


15

Let x, yมีสองจำนวนจุดลอยตัว วิธีที่ถูกต้องในการคำนวณค่าเฉลี่ยของพวกเขาคืออะไร?

วิธีไร้เดียงสา(x+y)/2อาจส่งผลให้เกิดการล้นเมื่อxและyมีขนาดใหญ่เกินไป ฉันคิดว่า0.5 * x + 0.5 * yอาจจะดีกว่า แต่มันเกี่ยวข้องกับการคูณสองครั้ง (ซึ่งอาจไม่มีประสิทธิภาพ) และฉันไม่แน่ใจว่ามันดีพอ มีวิธีที่ดีกว่า?

อีกความคิดหนึ่งที่ผมได้เล่นกับคือถ้า(y/2)(1 + x/y) x<=yแต่อีกครั้งฉันไม่แน่ใจว่าจะวิเคราะห์และพิสูจน์ว่าเป็นไปตามข้อกำหนดของฉัน

นอกจากนี้ผมต้องรับประกันว่าค่าเฉลี่ยจะคำนวณและ>= min(x,y) <= max(x,y)ตามที่ระบุไว้ในคำตอบของ Don Hatchอาจเป็นวิธีที่ดีกว่าในการวางคำถามนี้: การใช้ค่าเฉลี่ยของตัวเลขสองตัวที่ให้ผลลัพธ์ที่แม่นยำที่สุดเท่าที่จะเป็นไปได้คืออะไร นั่นคือถ้าxและyเป็นตัวเลข floating-point จะคำนวณตัวเลข floating-point ได้(x+y)/2อย่างไร? ในกรณีนี้หมายถึงการคำนวณโดยอัตโนมัติและ>= min(x,y) <= max(x,y)ดูคำตอบของ Don Hatchสำหรับรายละเอียด

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


(+1) คำถามที่น่าสนใจไม่น่าแปลกใจ
คิริลล์

1
ในอดีตค่าจุดลอยตัวจะถูกคำนวณและจัดขึ้นในรูปแบบที่มีความแม่นยำสูงสำหรับผลลัพธ์ระดับกลาง หาก a + b (64- บิตเป็นสองเท่า) จะสร้างผลลัพธ์กลาง 80 บิตและนี่คือสิ่งที่หารด้วย 2 คุณไม่ต้องกังวลเกี่ยวกับการล้น การสูญเสียความแม่นยำไม่ชัดเจน
JDługosz

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

ไม่ต้องกังวลเกี่ยวกับค่าใช้จ่ายของการคูณและการหารสอง คอมไพเลอร์ของคุณจะปรับให้เหมาะสมสำหรับคุณ
Federico Poloni

คำตอบ:


18

ฉันคิดว่าความแม่นยำและความเสถียรของอัลกอริธึมเชิงตัวเลขของไฮตั้มจะบอกถึงวิธีการวิเคราะห์ปัญหาเหล่านี้ ดูบทที่ 2 โดยเฉพาะอย่างยิ่งการออกกำลังกาย 2.8

ในคำตอบนี้ฉันต้องการชี้ให้เห็นสิ่งที่ไม่ได้กล่าวถึงในหนังสือของ Higham (ดูเหมือนจะไม่เป็นที่รู้จักอย่างกว้างขวางสำหรับเรื่องนั้น) หากคุณสนใจที่จะพิสูจน์คุณสมบัติของอัลกอริธึมเชิงตัวเลขอย่างง่ายเช่นนี้คุณสามารถใช้พลังของนักแก้ปัญหา SMT ที่ทันสมัย ​​( ทฤษฎีโมดูโลที่น่าพอใจ ) เช่นz3โดยใช้แพ็คเกจเช่นsbvใน Haskell ค่อนข้างง่ายกว่าการใช้ดินสอกับกระดาษ

สมมติว่าผมให้ที่และผมอยากจะรู้ว่าถ้าZ = ( x + Y ) / 2 satisfies x Z Y รหัส Haskell ต่อไปนี้0xyz=(x+y)/2xzy

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เป็นเรื่องที่สำหรับทุก จำกัด ลอยx , y ที่มี0 x Yxfun(x,y)yx,y0xy

λ> prove $ test1 (\x y -> (x + y) / 2)
Falsifiable. Counter-example:
  x = 2.3089316e36 :: Float
  y = 3.379786e38 :: Float

มันล้น สมมติว่าฉันใช้สูตรอื่นของคุณ: 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

ใช้งานไม่ได้ (เนื่องจากมีอันเดอร์อย่างค่อยเป็นค่อยไป: ซึ่งอาจใช้งานไม่ได้เนื่องจากเลขคณิตทั้งหมดเป็นฐาน -2)(x/2)×2x

ตอนนี้ลอง :Z=x+(Y-x)/2

λ> prove $ test1 (\x y -> x + (y-x)/2)
Q.E.D.

Works! นี่Q.E.D.คือข้อพิสูจน์ว่าtest1ทรัพย์สินมีไว้สำหรับการลอยตัวตามที่กำหนดไว้ข้างต้น

มีอะไรที่เหมือนกัน แต่ จำกัด ไว้ที่ (แทนที่จะเป็น0 x y )xY0xY

λ> prove $ test2 (\x y -> x + (y-x)/2)
Falsifiable. Counter-example:
  x = -3.1300826e34 :: Float
  y = 3.402721e38 :: Float

ตกลงดังนั้นถ้าโอเวอร์โฟลว์แล้ว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.

ดังนั้นดูเหมือนว่าในบรรดาสูตรที่ฉันได้ลองที่นี่ดูเหมือนว่าจะทำงานได้ (พร้อมการพิสูจน์ด้วย) วิธีแก้ปัญหาแบบ SMT ดูเหมือนจะเป็นวิธีที่รวดเร็วกว่าในการตอบข้อสงสัยเกี่ยวกับสูตรจุดลอยตัวที่ง่ายกว่าการวิเคราะห์ข้อผิดพลาดจุดลอยตัวด้วยดินสอและกระดาษx+(Y/2-x/2)

ในที่สุดเป้าหมายของความแม่นยำและความเสถียรมักจะขัดแย้งกับเป้าหมายของการปฏิบัติงาน สำหรับประสิทธิภาพฉันไม่เห็นว่าคุณจะทำได้ดีกว่าโดยเฉพาะอย่างยิ่งเนื่องจากคอมไพเลอร์จะยังคงยกการแปลนี้เป็นคำแนะนำสำหรับเครื่องของคุณอย่างหนัก(x+Y)/2

PSสิ่งนี้คือทั้งหมดที่มีความแม่นยำเลขทศนิยม IEEE754 ฉันตรวจสอบด้วยเลขคณิตความแม่นยำสองเท่า (แทนที่ด้วย) และใช้งานได้เช่นกันxx+(Y/2-x/2)YSFloatSDouble

PPSสิ่งหนึ่งที่ควรคำนึงถึงเมื่อใช้สิ่งนี้ในรหัสคือคอมไพเลอร์แฟล็กเช่น-ffast-math(บางรูปแบบของแฟล็กดังกล่าวเปิดตามค่าเริ่มต้นในคอมไพเลอร์ทั่วไปบางตัว) จะไม่ส่งผลให้เกิดเลขคณิต IEEE754 ถ้าคุณทำธงที่ช่วยให้การใช้งานเช่นการเพิ่มประสิทธิภาพนอกจากนี้ยังเชื่อมโยงแล้วมีจุดในการทำสิ่งอื่นที่ไม่ใช่ไม่มี 2(x+Y)/2

PPPSฉันถูกมองไปที่นิพจน์พีชคณิตแบบง่าย ๆ โดยที่ไม่มีเงื่อนไข สูตรของDon Hatchดีกว่าอย่างเคร่งครัด


2
ยึดมั่นใน; คุณอ้างว่าถ้า x <= y (ไม่ว่า x> = 0 หรือไม่) ดังนั้น x + (y / 2-x / 2) เป็นวิธีที่ดีในการทำหรือไม่? ดูเหมือนว่าฉันจะไม่ถูกต้องเพราะมันให้คำตอบที่ผิดในกรณีต่อไปนี้เมื่อคำตอบนั้นสามารถแทนได้: x = -1, y = 1 + 2 ^ -52 (จำนวนน้อยที่สุดแทนได้มากกว่า 1), ในกรณีนี้คำตอบคือ 2 ^ -53 การยืนยันในไพ ธ อน: >>> x = -1.; y = 1.+2.**-52; print `2**-53`, `(x+y)/2.`, `x+(y/2.-x/2.)`
Don Hatch

2
@ DonHatch ฉันมีเป้าหมายที่จะตอบคำถามเกี่ยวกับ "ความทนทาน": สร้างความมั่นใจว่าความไม่เท่าเทียมกันยังคงมีอยู่และไม่มีอะไรภายใต้ / ล้น ที่สำคัญตัวอย่างที่คุณให้นั้นไม่เสถียรในความหมายของเงื่อนไขขนาดใหญ่: การเยี่ยงอย่างของสัมพัทธ์ขนาดเล็กในx , yทำให้เกิดการเปลี่ยนแปลงสัมพัทธ์จำนวนมากในผลลัพธ์เช่นการยกเลิกหายนะ นอกเหนือจากที่คุณพูดถูก: ( x + y ) / 2จะให้ผลลัพธ์ที่ถูกต้องเสมอโดยมีข้อผิดพลาดสัมพัทธ์เล็กน้อย ฉันจะชอบมากกว่านี้( x + yx(x+Y)/2Yx,Y(x+Y)/2(x+Y)/2

8

ก่อนอื่นให้สังเกตว่าหากคุณมีวิธีการที่ให้คำตอบที่แม่นยำที่สุดในทุกกรณีมันจะตอบสนองเงื่อนไขที่คุณต้องการ (หมายเหตุที่ผมพูดคำตอบที่ถูกต้องที่สุดมากกว่าคำตอบที่ถูกต้องที่สุดเนื่องจากอาจจะมีสองผู้โชคดี.) มีหลักฐาน: ถ้าจะตรงกันข้ามคุณมีคำตอบที่ถูกต้องตามที่เป็นไปได้ที่ไม่ได้ตามเงื่อนไขที่ต้องการที่ หมายถึงอย่างใดอย่างหนึ่ง(ในกรณีนี้คือคำตอบที่ดีกว่าความขัดแย้ง) หรือ(ซึ่งในกรณีนี้คือคำตอบที่ดีกว่าความขัดแย้ง)answer<min(x,y)<=max(x,y)min(x,y)min(x,y)<=max(x,y)<answermax(x,y)

ดังนั้นฉันคิดว่านั่นหมายความว่าคำถามของคุณจะลดลงเพื่อค้นหาคำตอบที่แม่นยำที่สุด สมมติว่าเลขคณิต IEEE754 ตลอดฉันเสนอสิ่งต่อไปนี้

if max(abs(x),abs(y)) >= 1.:
    return x/2. + y/2.
else:
    return (x+y)/2.

ข้อโต้แย้งของฉันว่าสิ่งนี้ให้คำตอบที่ถูกต้องที่สุดคือการวิเคราะห์กรณีที่ค่อนข้างน่าเบื่อ ไปที่นี่:

  • Case max(abs(x),abs(y)) >= 1.:

    • Subcase จะไม่มี x และ y เป็น denormalized: ในกรณีนี้คำตอบที่คำนวณนั้นจะx/2.+y/2.จัดการ mantissas เดียวกันดังนั้นจึงให้คำตอบที่แน่นอนเหมือนกับการคำนวณ(x+y)/2จะให้ผลถ้าเราสันนิษฐานว่า exponents แบบขยายเพื่อป้องกันการล้น คำตอบนี้อาจขึ้นอยู่กับโหมดการปัดเศษ แต่ในกรณีใด ๆ มันรับประกันโดย IEEE754 เป็นคำตอบที่ดีที่สุด (จากข้อเท็จจริงที่ว่าการคำนวณx+yนั้นรับประกันว่าจะเป็นการประมาณที่ดีที่สุดสำหรับคณิตศาสตร์ x + y และการหารด้วย 2 แน่นอนในนี้ กรณี).
    • Subcase x ถูกทำให้เป็นปกติ (และอื่น ๆabs(y)>=1):

      answer = x/2. + y/2. = y/2. since abs(x/2.) is so tiny compared to abs(y/2.) = the exact mathematical value of y/2 = a best possible answer.

    • Subcase y ถูกทำให้เป็นปกติ (และอื่น ๆabs(x)>=1): คล้ายคลึงกัน

  • Case max(abs(x),abs(y)) < 1.:
    • Subcase การคำนวณx+yนั้นไม่ใช่แบบ denormalized หรือ denormalized-and- "แม้": แม้ว่าการคำนวณx+yอาจจะไม่ถูกต้อง แต่ IEEE754 รับประกันว่าจะเป็นค่าประมาณที่ดีที่สุดในคณิตศาสตร์ x + y ในกรณีนี้การหารด้วย 2 ในนิพจน์(x+y)/2.นั้นแน่นอนดังนั้นคำตอบที่คำนวณได้(x+y)/2.คือการประมาณที่ดีที่สุดสำหรับคณิตศาสตร์ (x + y) / 2
    • Subcase การคำนวณx+yคือ denormalized และ "คี่": ในกรณีนี้หนึ่งใน x, y จะต้องเป็น denormalized - และ - "คี่" ซึ่งหมายถึงอีกอันของ x, y คือ denormalized ด้วยเครื่องหมายตรงข้ามและดังนั้นการคำนวณx+yคือ คณิตศาสตร์ x + y อย่างแน่นอนและดังนั้นการคำนวณที่ได้(x+y)/2.รับการรับรองโดย IEEE754 จะเป็นการประมาณที่ดีที่สุดที่เป็นไปได้ทางคณิตศาสตร์ (x + y) / 2

ฉันรู้ตัวเมื่อฉันพูดว่า "denormalized" ฉันหมายถึงอย่างอื่น - นั่นคือตัวเลขที่ใกล้เคียงกันมากที่สุดเท่าที่ตัวเลขจะได้รับนั่นคือช่วงของตัวเลขที่มีขนาดใหญ่เป็นสองเท่าของช่วงของตัวเลข คือ 8 เห็บแรกหรือดังนั้นในแผนภาพที่en.wikipedia.org/wiki/Denormal_number ประเด็นคือคนที่ "แปลก" ในจำนวนนี้เป็นเพียงตัวเลขเดียวเท่านั้นที่หารด้วยสองไม่แม่นยำ ฉันต้องการวลีอีกส่วนหนึ่งของคำตอบเพื่อให้ชัดเจน
Don Hatch

ล.(โอพี(x,Y))=โอพี(x,Y)(1+δ)|δ|ยูx/2+Y/2(x+Y)/2มีการปัดเศษอย่างถูกต้องเสมอขาดเกิน / / อันเดอร์ทั้งหมดที่เหลืออยู่คือไม่ต้องแสดงอะไรมากไป - / อันเดอร์โฟลว์ซึ่งเป็นเรื่องง่าย
คิริลล์

@ คิริลฉันหลงทาง ... คุณมาจากไหน? นอกจากนี้ฉันไม่คิดว่ามันเป็นความจริงที่ว่า "การหารด้วย 2 นั้นแน่นอนสำหรับตัวเลขที่ไม่ใช่ตัวเลข" ... นี่เป็นสิ่งเดียวกับที่ฉันสะดุดมากกว่าและดูเหมือนว่าจะเป็นเรื่องที่น่าอึดอัดใจเล็กน้อยที่จะพยายามทำให้ถูกต้อง คำสั่งที่แม่นยำเป็นอะไรที่มากกว่า "x / 2 แน่นอนตราบใดที่ abs (x) เป็นอย่างน้อยสองเท่าของจำนวนที่น้อยกว่าปกติมากที่สุด" ... เอ้ย!
Don Hatch

3

สำหรับรูปแบบเลขทศนิยมทศนิยม IEEE-754 ไบนารีสุดขั้วโดยbinary64การคำนวณ (ความแม่นยำสองเท่า) S. Boldo พิสูจน์อย่างเป็นทางการว่าอัลกอริทึมแบบง่ายที่แสดงด้านล่างให้ค่าเฉลี่ยกลมที่ถูกต้อง

Sylvie Boldo "การตรวจสอบอย่างเป็นทางการของโปรแกรมคำนวณค่าเฉลี่ยของจำนวนจุดลอยตัว" ในการประชุมนานาชาติเกี่ยวกับระเบียบวิธีทางวิศวกรรม , หน้า 17-32 Springer, Cham, 2015. ( ฉบับร่างออนไลน์ )

(x+Y)/2x/2+Y/2binary64[2-967,2970] เพื่อมอบประสิทธิภาพที่ดีที่สุดสำหรับกรณีการใช้งานเฉพาะ

สิ่งนี้ให้ISO-C99โค้ดที่เป็นแบบอย่างดังต่อไปนี้:

double average (double x, double y) 
{
    const double C = 1; /* 0x1p-967 <= C <= 0x1p970 */
    return (C <= fabs (x)) ? (x / 2 + y / 2) : ((x + y) / 2);
}

ในงานติดตามล่าสุด Boldo และผู้เขียนร่วมแสดงวิธีการบรรลุผลลัพธ์ที่ดีที่สุดที่เป็นไปได้สำหรับรูปแบบทศนิยมทศนิยม IEEE-754 โดยใช้การดำเนินการ fused multiply-add (FMA) และความแม่นยำที่รู้จักกันดี - การสร้างบล็อคสองเท่า (TwoSum):

Sylvie Boldo, Florian Faissole และ Vincent Tourneur "อัลกอริทึมที่ผ่านการพิสูจน์อย่างเป็นทางการเพื่อคำนวณค่าเฉลี่ยที่ถูกต้องของตัวเลขทศนิยมแบบทศนิยม" ในการประชุมวิชาการ IEEE ครั้งที่ 25 เรื่องการคำนวณทางคอมพิวเตอร์ (ARITH 25) , มิถุนายน 2018, หน้า 69-75 ( ร่างออนไลน์ )


2

แม้ว่ามันอาจจะไม่ใช่ประสิทธิภาพที่ยอดเยี่ยม แต่ก็มีวิธีที่ง่ายมากในการ(1)ตรวจสอบให้แน่ใจว่าไม่มีตัวเลขใดมากกว่าxหรือy(ไม่มีโอเวอร์โฟลว์) และ(2)เก็บจุดลอยตัวว่า "ถูกต้อง" เป็นไปได้ (และ(3)เป็นโบนัสเพิ่มแม้ว่าจะใช้การลบก็ตามจะไม่มีการบันทึกค่าใด ๆ เป็นตัวเลขติดลบ

float difference = max(x, y) - min(x, y);
return min(x, y) + (difference / 2.0);

ในความเป็นจริงถ้าคุณจริงๆต้องการที่จะไปเพื่อความถูกต้องคุณไม่จำเป็นต้องดำเนินการในส่วนที่อยู่ในจุดที่; เพียงคืนค่าของmin(x, y)และdifferenceที่คุณสามารถใช้เพื่อลดความซับซ้อนของเหตุผลหรือจัดการในภายหลัง


สิ่งที่ฉันพยายามคิดตอนนี้คือการทำให้คำตอบเดียวกันนี้ทำงานได้มากกว่าสองรายการในขณะที่ทำให้ตัวแปรทั้งหมดยังคงต่ำกว่าตัวเลขที่มากที่สุดและใช้การดำเนินการหารเดียวเพื่อรักษาความถูกต้อง
IQAndreas

@becko Yup คุณจะต้องแบ่งอย่างน้อยสองครั้ง ตัวอย่างที่คุณให้ไว้จะทำให้คำตอบออกมาผิด ลองนึกภาพเฉลี่ยของมันไม่ได้เป็นเช่นเดียวกับค่าเฉลี่ยของ2,4,9 3,9
IQAndreas

คุณพูดถูกการโทรซ้ำของฉันไม่ถูกต้อง ฉันไม่แน่ใจว่าจะแก้ไขได้อย่างไรตอนนี้โดยไม่สูญเสียความแม่นยำ
becko

คุณสามารถพิสูจน์ได้ว่าสิ่งนี้ให้ผลลัพธ์ที่แม่นยำที่สุดใช่หรือไม่ นั่นคือถ้าxและyเป็น floating-point การคำนวณของคุณจะสร้าง floating-point ใกล้เคียงที่สุด(x+y)/2?
becko

1
จะไม่เกินนี้เมื่อ x, y เป็นตัวเลขที่น้อยที่สุดและชัดเจนที่สุด?
Don Hatch

1

แปลงเป็น precission ที่สูงขึ้นเพิ่มค่าที่นั่นและแปลงกลับ

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

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


นี่คือวิธีการที่กำลังดุร้าย อาจใช้งานได้ แต่ฉันกำลังมองหาการวิเคราะห์ที่ไม่ต้องการความแม่นยำสูงกว่าระดับกลาง นอกจากนี้คุณสามารถประมาณว่าต้องการความแม่นยำสูงระดับกลางได้มากเท่าใด ไม่ว่าในกรณีใดอย่าลบคำตอบนี้ (+1) ฉันแค่ไม่ยอมรับมันเป็นคำตอบ
becko

1

ในทางทฤษฎีx/2สามารถคำนวณได้โดยการลบ 1 จากแมนทิสซา

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

หากคุณสามารถทำได้การดำเนินการทั้งหมดจะลดลงเป็น 3 การบวก / ลบซึ่งควรเป็นการปรับปรุงที่สำคัญ


0

ฉันกำลังคิดตามบรรทัดเดียวกับ @Roland Heath แต่ยังไม่สามารถออกความเห็นได้นี่คือสิ่งที่ฉันต้องทำ:

x/2สามารถคำนวณได้โดยการลบ 1 จากเลขชี้กำลัง (ไม่ใช่แมนทิสซา, การลบ 1 จากแมนทิสซาจะถูกลบออก2^(value_of_exponent-length_of_mantissa)จากค่าโดยรวม)

โดยไม่มีข้อ จำกัด x < yในกรณีทั่วไปสมมติ (ถ้าx > y, ติดฉลากตัวแปรใหม่x = y, หาก(x+y) / 2เป็นเรื่องเล็กน้อย)

  • แปลง(x+y) / 2เป็นรูปx/2 + y/2ซึ่งสามารถทำได้โดยการลบจำนวนเต็มสองค่า (โดยลบจากเลขชี้กำลังหนึ่งตัว)
    • อย่างไรก็ตามมีขีด จำกัด ล่างของเลขชี้กำลังทั้งนี้ขึ้นอยู่กับการเป็นตัวแทนของคุณ หากเลขชี้กำลังของคุณมีน้อยที่สุดก่อนที่จะลบ 1 วิธีนี้จะต้องใช้การจัดการตัวพิมพ์พิเศษ เลขชี้กำลังขั้นต่ำที่xจะทำให้x/2มีขนาดเล็กกว่าที่สามารถแทนได้ (สมมติว่า mantissa มีการแสดงด้วย 1 นำโดยนัย)
    • แทนที่จะลบ 1 จากเลขชี้กำลังxให้เปลี่ยนxmantissa ของไปทางขวาทีละหนึ่ง (และเพิ่มค่านำหน้า 1 โดยนัยถ้ามี)
    • ลบ 1 จากเลขชี้กำลังของ y หากไม่ได้น้อยที่สุด หากมันน้อยที่สุด (y มากกว่า x เนื่องจาก mantissa) ให้เลื่อน mantissa ไปทางขวาทีละหนึ่ง (เพิ่มนำหน้าโดยนัย 1 ถ้ามี)
    • เปลี่ยน mantissa ใหม่เพื่อให้เป็นไปตามสิทธิที่จะยกกำลังของxy
    • ดำเนินการเพิ่มจำนวนเต็มบน mantissae ยกเว้นว่า mantissa ของxถูกเลื่อนออกไปอย่างสมบูรณ์ หากทั้งสองเลขชี้กำลังมีน้อยที่สุดคนที่เป็นผู้นำจะล้นซึ่งก็โอเคเพราะน้ำล้นนั้นควรจะกลายเป็นผู้นำโดยนัยอีกครั้ง
  • และอีกหนึ่งจุดลอย
    • นึกถึงกรณีพิเศษไม่ได้ที่นี่ ยกเว้นการปัดเศษซึ่งใช้กับการเลื่อนที่อธิบายไว้ข้างต้น
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.