เหตุใดค่าลบศูนย์จึงสำคัญ


64

ฉันสับสนเกี่ยวกับสาเหตุที่เราสนใจการเป็นตัวแทนที่แตกต่างกันสำหรับศูนย์บวกและลบ

ฉันเรียกคืนการอ่านอย่างคลุมเครืออ้างว่าการมีค่าลบศูนย์เป็นสิ่งสำคัญอย่างยิ่งในการเขียนโปรแกรมที่เกี่ยวข้องกับตัวเลขที่ซับซ้อน ฉันไม่เคยมีโอกาสเขียนโค้ดที่เกี่ยวกับตัวเลขที่ซับซ้อนดังนั้นฉันรู้สึกสับสนเล็กน้อยเกี่ยวกับสาเหตุที่เป็นเช่นนี้

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

เหตุใดค่าลบศูนย์จึงมีค่าในการคำนวณ ฉันแน่ใจว่าฉันเพิ่งพลาดบางสิ่ง


6
ศูนย์ลบสามารถส่งสัญญาณ underflow ในจำนวนจุดลอยตัวของ IEEE แต่ยิ่งไปกว่านั้นการใช้งานดูเหมือนจะขัดแย้งและคลุมเครือ ถ้าฉันต้องเดาฉันจะบอกว่าศูนย์ลบเป็นตัวแทนในจุดลอยตัวของ IEEE เพราะ ... คุณก็ทำได้ สำหรับการขับขี่ที่น่าสนใจยิ่งขึ้นให้ค้นหาข้อมูลเกี่ยวกับการส่งสัญญาณจุดลอยตัวที่ NaN
Robert Harvey

1
หากตัวอย่างเฉพาะคือ "1 / 0.0" / "1 / -0.0", 0 คือการตัดสาขาสำหรับ 1 / x และข้อ จำกัด ขึ้นอยู่กับว่าคุณเข้าหาจากด้านล่างหรือด้านบน
Vatine

@Vatine ไม่ตัวอย่างที่เฉพาะเจาะจงคือsqrt(-1+0i) = iและsqrt(-1-0i) = -iถึงแม้ว่าแต่งตัวด้วยไวยากรณ์ที่เหมาะสมสำหรับภาษาการเขียนโปรแกรมบางอย่างผมเชื่อว่า ฉันจะแก้ไขให้ชัดเจนยิ่งขึ้น
jpmc26

3
ฉันค้นหาโปรแกรมเมอร์ , Stack มากเกิน , วิทยาการคอมพิวเตอร์ , คณิตศาสตร์และวิศวกรรม คำถามเดียวที่ฉันสามารถหาได้คือใช้เพื่อลบค่าทศนิยมของศูนย์ . นี่เป็นเพียงครั้งที่สองที่เกิดขึ้น!

ฉันประหลาดใจจริงๆที่จำนวนเชิงซ้อนไม่ได้เกิดขึ้นเลยในคำตอบโดยเฉพาะอย่างยิ่งจากตัวอย่างรากที่สองที่ฉันชี้ให้เห็น
jpmc26

คำตอบ:


69

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

a = -1 / 1000000000000000000.0

a มีขนาดเล็กเกินไปที่จะแสดงอย่างถูกต้องด้วยการลอย (32 บิต) ดังนั้นมันจึงเป็น "การปัดเศษ" ถึง -0

สมมติว่าการคำนวณของเราดำเนินต่อไป:

b = 1 / a

เนื่องจาก a คือ float มันจะทำให้ - infinity ซึ่งค่อนข้างไกลจากคำตอบที่ถูกต้องของ -10000000000000000000000.0

ทีนี้ลองคำนวณ b ถ้าไม่มี -0 (ดังนั้น a ถูกปัดเศษเป็น +0):

b = 1 / +0
b = +infinity

ผลลัพธ์ไม่ถูกต้องอีกครั้งเนื่องจากการปัดเศษ แต่ตอนนี้มันเป็น "ผิดพลาดมากกว่า" - ไม่เพียง แต่เป็นตัวเลข แต่ที่สำคัญกว่านั้นเพราะสัญญาณต่างกัน (ผลลัพธ์ของการคำนวณคือ + อินฟินิตี้ผลลัพธ์ที่ถูกต้องคือ -1000000000000000000.0)

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


คุณมีความคิดใด ๆ หรือไม่ว่าเครื่องหมายของอันเดอร์โฟลว์อาจมีความสำคัญเป็นพิเศษในการคำนวณจำนวนจินตภาพ / ซับซ้อนหรือไม่?
jpmc26

@qbd: คุณรู้ไหมว่าแอปพลิเคชั่นตัวเลขเหล่านั้นคืออะไร? ฉันจะบอกว่าโปรแกรมที่ทริกเกอร์และใช้งาน+infและ-infในการทำงานปกตินั้นมีข้อบกพร่อง
Björn Lindqvist

@ BjörnLindqvistหากคุณต้องการแอพพลิเคชั่นที่สามารถดาวน์โหลดได้ - ฉันไม่รู้อะไรเลย ฉันไม่คิดว่ามันเป็นรถที่จำเป็น - แทนที่จะใช้แบบลอย / สองเท่าคุณสามารถใช้สิ่งที่ต้องการ BigDecimal ด้วยความแม่นยำที่ไม่ จำกัด แต่มันจะคุ้มค่าหรือไม่เมื่อโปรแกรมจะให้ผลลัพธ์เหมือนกับที่เป็นแบบ float / double แต่จะมีประสิทธิภาพที่แย่กว่านี้มาก
qbd

คุณเขียนว่า "การประยุกต์ใช้ตัวเลขที่ผลที่สำคัญที่สุดของการคำนวณเป็นสัญญาณ" ฉันสามารถเชื่อว่า แต่ฉันไม่สามารถเชื่อว่ามีการใช้งานที่ดีเขียนใด ๆ ที่ต้องพึ่งพา -0 และค่าถูกและ+inf -infหากโปรแกรมของคุณทำให้เกิดจุดลอยตัวอันเดอร์โฟล์วนั่นคือจุดบกพร่องและสิ่งที่เกิดขึ้นหลังจากนั้นไม่น่าสนใจเท่าไหร่ เรายังขาดตัวอย่างเชิงปฏิบัติที่เป็นประโยชน์ -0
Björn Lindqvist

1
@ BjörnLindqvistส่วนใหญ่ของ x265 นั้นทำขึ้นในแอสเซมบลีโดยอาศัยรายละเอียดที่คลุมเครือ (ซึ่งขึ้นอยู่กับสถาปัตยกรรมของ CPU) มีคนไม่กี่คนที่รู้เกี่ยวกับชื่อของประสิทธิภาพ มันผิดไหม? อาศัยมาตรฐานอายุ 30 ปีที่ใช้กันอย่างแพร่หลาย (ซึ่งอยู่ที่นี่) สำหรับคุณสมบัติที่เรียบง่ายและเข้าใจได้ง่ายในชื่อของประสิทธิภาพในทันใดดูเหมือนไม่เลวเลย
qbd

8

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

การมีศูนย์ติดลบทำให้การคูณและการหารง่ายขึ้นเล็กน้อยเครื่องหมายของ x * y หรือ x / y มักเป็นเครื่องหมายของ x, เอกสิทธิ์หรือสัญลักษณ์ของ y หากไม่มีศูนย์ติดลบจะต้องมีการตรวจสอบพิเศษเพื่อแทนที่ -0 ด้วย +0

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

การเพิ่มประสิทธิภาพคอมไพเลอร์เกลียด -0 ตัวอย่างเช่นคุณไม่สามารถแทนที่ x + 0.0 ด้วย x ได้เนื่องจากผลลัพธ์ไม่ควรเป็น x หาก x คือ -0.0 คุณไม่สามารถแทนที่ x * 0.0 ด้วย 0.0 เนื่องจากผลลัพธ์ควรเป็น -0.0 ถ้า x <0 หรือ x คือ -0.0


7
ฉันหวังว่า IEEE-754 ได้รวมศูนย์สี่: "แน่นอน", บวกน้อย, ลบเล็กและไม่ได้ลงนาม (หลังเป็นความแตกต่างระหว่างค่าแยกไม่ออก) การทำเช่นนั้นจะทำให้งานสัจพจน์จุดลอยตัวจำนวนมาก - ในหมู่พวกเขา, x + 0.0 equiv x-0.0 equiv x, xy equiv x + (- 1.0) * y, และ 1.0 / x equiv -1.0 / (- 1.0 * x) [ถ้า x เป็นศูนย์บวกทั้งคู่จะเป็น pos-inf; ถ้า neg-zero ทั้ง neg-inf; ถ้าแน่นอนหรือไม่ได้ลงนามทั้ง NaN]
supercat

ฉันก็สามารถที่จะได้รับการลบศูนย์โดยการส่งผ่าน-5และเข้า5 fmod()มันค่อนข้างน่ารำคาญสำหรับกรณีการใช้งานของฉัน
Aaron Franke

6

C # Double ซึ่งสอดคล้องกับ IEEE 754

    double a = 3.0;
    double b = 0.0;
    double c = -0.0;

    Console.WriteLine(a / b);
    Console.WriteLine(a / c);

พิมพ์:

Infinity
-Infinity

จริง ๆ แล้วจะอธิบายเล็กน้อย ...

Double d = -0.0; 

นี่หมายถึงบางสิ่งที่ใกล้กับ d = The Limit of x as x approaches 0-หรือ The Limit of x as x approaches 0 from the negativesมาก


เพื่อแสดงความคิดเห็นของ Philipp ...

โดยทั่วไปศูนย์ลบหมายถึง underflow

มีประโยชน์น้อยมากสำหรับการลบศูนย์ถ้ามี ...

ตัวอย่างเช่นรหัสนี้ (อีกครั้ง C #):

double a = -0.0;
double b = 0.0;

Console.WriteLine(a.Equals(b));
Console.WriteLine(a==b);
Console.WriteLine(Math.Sign(a));

ให้ผลลัพธ์นี้:

True
True
0

เพื่ออธิบายอย่างไม่เป็นทางการค่าพิเศษทั้งหมดที่จุดลอยตัว IEEE 754 สามารถมีได้ (อินฟินิตี้บวก, ลบอนันต์, NAN, -0.0) ไม่มีความหมายในทางปฏิบัติ พวกเขาไม่สามารถแทนค่าทางกายภาพใด ๆ หรือค่าใด ๆ ที่สมเหตุสมผลในการคำนวณ "โลกแห่งความจริง" สิ่งที่พวกเขาหมายถึงเป็นพื้นนี้:

  • บวกอนันต์หมายถึงการไหลล้นที่ปลายบวกจุดลอยตัวสามารถเป็นตัวแทน
  • ลบอนันต์หมายถึงการไหลล้นที่ปลายบวกจุดลอยตัวสามารถเป็นตัวแทน
  • ศูนย์ลบหมายถึงอันเดอร์โฟล์และตัวถูกดำเนินการมีเครื่องหมายตรงกันข้าม
  • ศูนย์บวกอาจหมายถึงอันเดอร์โฟล์และตัวถูกดำเนินการมีเครื่องหมายเดียวกัน
  • NAN หมายถึงการคำนวณของคุณนั้นไม่ได้กำหนดไว้อย่างถูกใจเช่นsqrt(-7)หรือไม่มีขีด จำกัด เช่น 0/0หรือชอบPositiveInfinity/PositiveInfinity

7
ใช่ แต่ทำไมเรื่องนี้ถึงสำคัญ คุณสามารถให้ตัวอย่างที่ใช้งานจริงได้จริงซึ่งความแตกต่างมีความสำคัญอย่างไร
Philipp

5

คำถามเกี่ยวกับความเกี่ยวข้องกับการคำนวณจำนวนเชิงซ้อนจริง ๆ แล้วเป็นเหตุให้ทั้ง +0 และ -0 มีอยู่ในทศนิยม หากคุณศึกษาการวิเคราะห์เชิงซ้อนคุณจะค้นพบว่าฟังก์ชั่นต่อเนื่องจากคอมเพล็กซ์ถึงคอมเพล็กซ์อย่างรวดเร็วไม่สามารถถือว่าเป็น 'ที่มีคุณค่าเดียว' เว้นแต่ว่าจะมี 'นิยายสุภาพ' ที่เอาท์พุทเป็นสิ่งที่เรียกว่าพื้นผิว Riemann ตัวอย่างเช่นลอการิทึมที่ซับซ้อนกำหนดให้แต่ละอินพุตเอาต์พุตจำนวนมากอย่างไม่สิ้นสุด เมื่อคุณ 'เชื่อมต่อพวกมัน' เพื่อสร้างเอาต์พุตอย่างต่อเนื่องคุณจะพบกับชิ้นส่วนจริงทั้งหมดที่สร้างพื้นผิว 'เกลียวที่ไม่มีที่สิ้นสุด' รอบจุดกำเนิด เส้นโค้งต่อเนื่องที่ข้ามแกนแท้จริง 'ลงจากด้านบวกในจินตนาการ' และอีกเส้นโค้งหนึ่งที่ 'ล้อมรอบเสา' และข้ามแกนจริง '

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


1

เหตุผลง่ายกว่าปกติ

แน่นอนว่ามีแฮ็กจำนวนมากที่ดูดีมากและมีประโยชน์ (เช่นการปัดเศษ-0.0หรือ+0.0แต่สมมติว่าเรามีการแสดง int ที่ลงนามพร้อมเครื่องหมายลบ / เครื่องหมายบวกที่จุดเริ่มต้น (ฉันรู้ว่าแก้ไขด้วยรหัสไบนารี U2 ในจำนวนเต็มมักจะ แต่ถือว่าการเป็นตัวแทนที่ซับซ้อนน้อยกว่าของ double):

0 111 = 7
^ sign

เกิดอะไรขึ้นถ้ามีจำนวนลบ

1 111 = -7

ตกลงง่าย ๆ ลองแทน 0:

0 000 = 0

ไม่เป็นไรเช่นกัน แต่เกี่ยวกับ1 000อะไร ต้องเป็นหมายเลขต้องห้ามหรือไม่ ไม่ดีกว่า

ดังนั้นสมมติว่ามีศูนย์สองประเภท:

0 000 = +0
1 000 = -0

นั่นจะทำให้การคำนวณของเราง่ายขึ้นและให้คุณลักษณะเพิ่มเติมบางอย่างที่ปัดเศษขึ้น ดังนั้น+0และ-0มาจากปัญหาการแสดงเลขฐานสอง


6
ถ้าฉันอ่านอย่างถูกต้องคุณแค่บอกว่าคนกำหนดหรือใช้มาตรฐานไม่ต้องการไปสู่ปัญหาของการห้ามมัน ฉันไม่คิดว่าเหตุผลนี้ถือได้ถึงความจริงที่ว่าส่วนประกอบของ 2 ใช้การแทนค่า "ศูนย์ลบ" สำหรับจำนวนที่แตกต่างกันอย่างสิ้นเชิงและไม่มีตัวแทนศูนย์ลบ ดูบทความ Wikipedia ที่ฉันเชื่อมโยง
jpmc26

1
@ jpmc26 ฉันคิดว่ามีความจริงบางอย่างที่ไม่ห้ามไม่ให้มีการดำเนินการเพื่อให้มีกรณีพิเศษ ตามที่เป็นอยู่ทุกหมายเลขจะมีบิตการลงชื่อและสามารถลบล้างได้โดยการสลับบิต แม้ NaNs จะถูกเซ็นชื่อและการใช้งานสามารถ (แต่ไม่จำเป็นต้อง) เลือกสัญญาณที่เหมาะสมเมื่อสร้าง NaN หากลบศูนย์ไม่ได้อยู่ในการคำนวณที่ส่งผลให้ใน 0 ทุกคนจะต้องทำงานพิเศษเพื่อแก้ไขปัญหาขึ้นบิตเครื่องหมาย ฯลฯ
ฮอบส์

4
@ jpmc26 (เช่นในการคูณจำนวนสองจำนวนอื่น ๆ เครื่องหมายของผลลัพธ์คือ xor ของเครื่องหมายของ multiplicand และขนาดเป็นผลคูณของสองขนาดในชีวิตจริงสิ่งนี้ใช้ได้กับ -1 * 0 = - . 0. แต่ถ้าศูนย์บิตเครื่องหมายพลิกบางค่าไม่ใช่ศูนย์พิเศษสินค้าที่สามารถผลิต 0 จะมีการตรวจสอบและให้แน่ใจว่ามันไม่ได้ผลิตที่ค่าพิเศษโดยไม่ได้ตั้งใจทุกครั้ง)
ฮอบส์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.