ทำไม (inf + 0j) * 1 จึงประเมินเป็น inf + nanj


97
>>> (float('inf')+0j)*1
(inf+nanj)

ทำไม? สิ่งนี้ทำให้เกิดข้อบกพร่องที่น่ารังเกียจในรหัสของฉัน

เหตุใดจึงไม่1ระบุตัวตนแบบทวีคูณการให้(inf + 0j)?


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

1
อ้อและถ้าคุณพบว่านิสัยเหล่านี้ทำลายและต้องการที่จะเจาะเครื่องคอมพิวเตอร์ของคุณคุณมีความเห็นอกเห็นใจของฉัน
user541686

2
@Mehrdad เมื่อคุณเพิ่มองค์ประกอบที่ไม่ จำกัด เหล่านั้นมันจะไม่เป็นฟิลด์ อันที่จริงเนื่องจากไม่มีความเป็นกลางแบบทวีคูณอีกต่อไปจึงไม่สามารถเป็นเขตข้อมูลได้
Paul Panzer

@PaulPanzer: ใช่ฉันคิดว่าพวกเขาเพิ่งผลักดันองค์ประกอบเหล่านั้นในภายหลัง
user541686

1
ตัวเลขทศนิยม (แม้ว่าคุณจะไม่รวมอินฟินิตี้และ NaN) ไม่ใช่ฟิลด์ ข้อมูลประจำตัวส่วนใหญ่ที่เก็บไว้สำหรับเขตข้อมูลไม่ถือเป็นตัวเลขทศนิยม
plugwash

คำตอบ:


95

ค่า1นี้จะถูกแปลงเป็นจำนวนเชิงซ้อนก่อน1 + 0jซึ่งจะนำไปสู่การinf * 0คูณทำให้nanได้

(inf + 0j) * 1
(inf + 0j) * (1 + 0j)
inf * 1  + inf * 0j  + 0j * 1 + 0j * 0j
#          ^ this is where it comes from
inf  + nan j  + 0j - 0
inf  + nan j

8
สำหรับการตอบคำถาม "ทำไม ... ?" ขั้นตอนที่สำคัญที่สุดอาจเป็นขั้นตอนแรก1คือส่งไปที่1 + 0jใด
Warren Weckesser

5
โปรดทราบว่า C99 ระบุว่าประเภทจุดลอยตัวจริงไม่ได้รับการเลื่อนระดับเป็นแบบซับซ้อนเมื่อคูณด้วยประเภทที่ซับซ้อน (ส่วน 6.3.1.8 ของมาตรฐานฉบับร่าง) และเท่าที่ฉันรู้ว่าสิ่งเดียวกันนี้เป็นจริงกับ std :: complex ของ C ++ ส่วนหนึ่งอาจเป็นเพราะเหตุผลด้านประสิทธิภาพ แต่ก็หลีกเลี่ยง NaN ที่ไม่จำเป็นด้วย
benrg

@benrg ใน NumPy, นอกจากนี้ยังประเมินarray([inf+0j])*1 array([inf+nanj])สมมติว่าการคูณจริงเกิดขึ้นที่ไหนสักแห่งในโค้ด C / C ++ นั่นหมายความว่าพวกเขาเขียนโค้ดที่กำหนดเองเพื่อเลียนแบบพฤติกรรม CPython แทนที่จะใช้ _Complex หรือ std :: complex หรือไม่?
Marnix

1
@marnix มันมีส่วนเกี่ยวข้องมากกว่านั้น numpyมีคลาสกลางหนึ่งคลาสufuncซึ่งเกือบทุกตัวดำเนินการและฟังก์ชันได้มา ufuncดูแลการจัดการการแพร่ภาพความก้าวหน้าของผู้ดูแลระบบที่ยุ่งยากซึ่งทำให้การทำงานกับอาร์เรย์เป็นไปอย่างสะดวกสบาย การแบ่งแรงงานระหว่างผู้ปฏิบัติงานเฉพาะและเครื่องจักรทั่วไปอย่างแม่นยำยิ่งขึ้นคือผู้ปฏิบัติงานเฉพาะจะใช้ชุด "ลูปด้านในสุด" สำหรับการรวมกันขององค์ประกอบอินพุตและเอาท์พุตแต่ละประเภทที่ต้องการจัดการ เครื่องจักรทั่วไปดูแลลูปด้านนอกและเลือกลูปด้านในสุดที่ดีที่สุด ...
Paul Panzer

1
... ส่งเสริมประเภทที่ไม่ตรงกันตามที่กำหนด เราสามารถเข้าถึงรายชื่อของลูปภายในให้ผ่านtypesแอตทริบิวต์สำหรับnp.multiplyอัตราผลตอบแทนนี้['??->?', 'bb->b', 'BB->B', 'hh->h', 'HH->H', 'ii->i', 'II->I', 'll->l', 'LL->L', 'qq->q', 'QQ->Q', 'ee->e', 'ff->f', 'dd->d', 'gg->g', 'FF->F', 'DD->D', 'GG->G', 'mq->m', 'qm->m', 'md->m', 'dm->m', 'OO->O']เราจะเห็นว่ามีชนิดเกือบจะไม่มีการผสมโดยเฉพาะอย่างยิ่งไม่มีใครที่ลอยผสมกับความซับซ้อน"efdg" "FDG"
Paul Panzer

32

ในทางกลไกคำตอบที่ได้รับการยอมรับคือถูกต้อง แต่ฉันขอยืนยันว่าสามารถให้คำตอบที่ลึกกว่า

ก่อนอื่นการชี้แจงคำถามเป็นประโยชน์ในขณะที่ @PeterCordes กล่าวในความคิดเห็น: "มีข้อมูลประจำตัวแบบคูณสำหรับจำนวนเชิงซ้อนที่ทำงานบน inf + 0j หรือไม่" หรือกล่าวอีกนัยหนึ่งคือสิ่งที่ OP เห็นจุดอ่อนในการใช้งานคอมพิวเตอร์ของการคูณที่ซับซ้อนหรือมีบางอย่างที่ไม่เป็นไปตามแนวคิดกับinf+0j

คำตอบสั้น ๆ :

การใช้พิกัดเชิงขั้วเราสามารถดูการคูณที่ซับซ้อนเป็นการสเกลและการหมุน การหมุน "แขน" ที่ไม่มีที่สิ้นสุดแม้จะเป็น 0 องศาในกรณีของการคูณด้วยหนึ่งเราคาดไม่ถึงว่าจะวางปลายแขนด้วยความแม่นยำ จำกัด แน่นอนว่ามีบางอย่างที่ไม่ถูกต้องโดยพื้นฐานinf+0jกล่าวคือทันทีที่เราอยู่ที่ระยะอนันต์การชดเชยที่ จำกัด จะไม่มีความหมาย

คำตอบยาว:

ความเป็นมา: "เรื่องใหญ่" ที่คำถามนี้วนเวียนอยู่คือเรื่องของการขยายระบบของตัวเลข (คิดว่าเป็นจำนวนจริงหรือจำนวนเชิงซ้อน) เหตุผลหนึ่งที่เราอาจต้องการทำเช่นนั้นคือการเพิ่มแนวคิดเรื่องอินฟินิตี้หรือ "กระชับ" ถ้าคนหนึ่งเป็นนักคณิตศาสตร์ ยังมีเหตุผลอื่น ๆ อีกด้วย ( https://en.wikipedia.org/wiki/Galois_theory , https://en.wikipedia.org/wiki/Non-standard_analysis ) แต่เราไม่สนใจสิ่งเหล่านี้

การบีบอัดจุดเดียว

แน่นอนว่าส่วนขยายที่ยุ่งยากก็คือเราต้องการให้ตัวเลขใหม่เหล่านี้พอดีกับเลขคณิตที่มีอยู่ วิธีที่ง่ายที่สุดคือเพิ่มองค์ประกอบเดียวที่อินฟินิตี้ ( https://en.wikipedia.org/wiki/Alexandroff_extension ) และทำให้มันเท่ากันทุกอย่างยกเว้นศูนย์หารด้วยศูนย์ สิ่งนี้ใช้ได้กับตัวเลขจริง ( https://en.wikipedia.org/wiki/Projectively_extended_real_line ) และจำนวนเชิงซ้อน ( https://en.wikipedia.org/wiki/Riemann_sphere )

นามสกุลอื่น ๆ ...

ในขณะที่การย่อขนาดจุดเดียวนั้นเรียบง่ายและฟังดูดีในเชิงคณิตศาสตร์ แต่ก็มีการค้นหาส่วนขยายที่ "สมบูรณ์กว่า" ซึ่งประกอบด้วย infinties หลาย ๆ มาตรฐาน IEEE 754 สำหรับตัวเลขทศนิยมจริงมี + inf และ -inf ( https://en.wikipedia.org/wiki/Extended_real_number_line ) ดูเป็นธรรมชาติและตรงไปตรงมา แต่บังคับให้เรากระโดดผ่านห่วงและประดิษฐ์สิ่งต่างๆเช่น-0 https://en.wikipedia.org/wiki/Signed_zero

... ของระนาบซับซ้อน

แล้วส่วนขยายมากกว่าหนึ่ง inf ของระนาบเชิงซ้อนล่ะ?

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

เครื่องบินซับซ้อนมีทรงกลดสมมาตรธรรมชาติซึ่งความสัมพันธ์ในอย่างกับเลขคณิตซับซ้อนเท่าคูณเครื่องบินทั้งทาง e ^ phij 0เป็นเช่นเดียวกับพีหมุนรอบเรเดียน

ภาคผนวก G

ตอนนี้เพื่อให้สิ่งต่าง ๆ ง่ายและซับซ้อน fp เพียงแค่ใช้ส่วนขยาย (+/- inf, nan เป็นต้น) ของการใช้งานจำนวนจริงพื้นฐาน ตัวเลือกนี้อาจดูเป็นธรรมชาติมากจนไม่ถูกมองว่าเป็นทางเลือก แต่ลองมาดูความหมายกันดีกว่า การแสดงภาพอย่างง่ายของส่วนขยายของระนาบเชิงซ้อนนี้ดูเหมือน (I = infinite, f = finite, 0 = 0)

I IIIIIIIII I
             
I fffffffff I
I fffffffff I
I fffffffff I
I fffffffff I
I ffff0ffff I
I fffffffff I
I fffffffff I
I fffffffff I
I fffffffff I
             
I IIIIIIIII I

แต่เนื่องจากระนาบเชิงซ้อนที่แท้จริงเป็นระนาบที่เคารพการคูณที่ซับซ้อนการฉายภาพที่ให้ข้อมูลมากกว่า

     III    
 I         I  
    fffff    
   fffffff   
  fffffffff  
I fffffffff I
I ffff0ffff I
I fffffffff I
  fffffffff  
   fffffff   
    fffff    
 I         I 
     III    

ในการฉายภาพนี้เราเห็น "การกระจายที่ไม่สม่ำเสมอ" ของ infinities ที่ไม่เพียง แต่น่าเกลียด แต่ยังเป็นต้นตอของปัญหาที่ OP ได้รับความเดือดร้อน: infinities ส่วนใหญ่ (ในรูปแบบ (+/- inf, finite) และ (จำกัด , + / -inf) ถูกรวมเข้าด้วยกันที่ทิศทางหลักทั้งสี่ทิศทางอื่น ๆ ทั้งหมดจะแสดงด้วย infinities เพียงสี่ตัว (+/- inf, + -inf) ไม่น่าแปลกใจที่การขยายการคูณที่ซับซ้อนไปยังรูปเรขาคณิตนี้เป็นฝันร้าย .

ภาคผนวก G ของข้อมูลจำเพาะ C99 พยายามอย่างเต็มที่เพื่อให้ใช้งานได้รวมถึงการปรับเปลี่ยนกฎเกี่ยวกับวิธีการinfและnanการโต้ตอบ (โดยพื้นฐานแล้วสำคัญinfกว่าnan) ปัญหาของ OP ถูกหลีกเลี่ยงโดยการไม่ส่งเสริมการเรียลและเสนอประเภทจินตนาการล้วนๆให้ซับซ้อน แต่การที่ 1 จริงทำงานแตกต่างจากคอมเพล็กซ์ 1 ไม่ได้ทำให้ฉันเป็นทางออก กล่าวได้ว่าภาคผนวก G ไม่ได้ระบุอย่างเต็มที่ว่าผลิตภัณฑ์ของสอง infinities ควรเป็นเท่าใด

เราทำได้ดีกว่านี้ไหม

เป็นเรื่องที่น่าสนใจที่จะลองแก้ไขปัญหาเหล่านี้โดยการเลือกรูปทรงเรขาคณิตของ infinities ที่ดีกว่า ในการเปรียบเทียบกับเส้นจริงที่ขยายเราสามารถเพิ่มอินฟินิตี้หนึ่งตัวสำหรับแต่ละทิศทาง โครงสร้างนี้คล้ายกับระนาบโปรเจ็กต์ แต่ไม่รวมกันเป็นก้อนตรงข้ามกัน Infinities จะแสดงในพิกัดเชิงขั้ว inf xe ^ {2 omega pi i} การกำหนดผลิตภัณฑ์จะตรงไปตรงมา โดยเฉพาะอย่างยิ่งปัญหาของ OP จะได้รับการแก้ไขอย่างเป็นธรรมชาติ

แต่นี่คือจุดสิ้นสุดของข่าวดี ในวิธีที่เราสามารถเหวี่ยงกลับไปที่กำลังสองได้โดย --- ไม่เกินสมควร --- ต้องการให้ infinities รูปแบบใหม่ของเรารองรับฟังก์ชันที่ดึงส่วนจริงหรือจินตภาพของมันออกมา นอกจากนี้เป็นปัญหาอื่น การเพิ่ม infinities แบบ nonantipodal สองตัวเราจะต้องตั้งค่ามุมเป็น undefined เช่นnan(เราสามารถโต้แย้งได้ว่ามุมจะต้องอยู่ระหว่างมุมอินพุตทั้งสอง แต่ไม่มีวิธีง่ายๆในการแสดงว่า "nan-ness บางส่วน")

Riemann เพื่อช่วยเหลือ

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


นี่คือคำถามที่เกี่ยวข้องซึ่งได้รับคำตอบจากผู้ที่มีความสามารถในเรื่องนี้มากกว่าฉัน


5
nan != nanใช่เพราะ ฉันเข้าใจว่าคำตอบนี้เป็นเรื่องล้อเล่น แต่ฉันไม่เข้าใจว่าเหตุใดจึงควรเป็นประโยชน์กับ OP ตามที่เขียนไว้
cmaster - คืนสถานะโมนิกา

เนื่องจากรหัสในเนื้อหาคำถามไม่ได้ใช้งานจริง==(และเนื่องจากพวกเขายอมรับคำตอบอื่น ๆ ) ดูเหมือนว่าจะเป็นปัญหาในการที่ OP แสดงชื่อ ฉันเปลี่ยนชื่อเรื่องเพื่อแก้ไขความไม่สอดคล้องกันนั้น (จงใจยกเลิกครึ่งแรกของคำตอบนี้เพราะฉันเห็นด้วยกับ @cmaster นั่นไม่ใช่สิ่งที่คำถามนี้ถาม)
Peter Cordes

3
@PeterCordes ที่น่าหนักใจเพราะการใช้พิกัดเชิงขั้วเราสามารถดูการคูณที่ซับซ้อนเป็นมาตราส่วนและการหมุนได้ การหมุน "แขน" ที่ไม่มีที่สิ้นสุดแม้จะเป็น 0 องศาในกรณีของการคูณด้วยหนึ่งเราคาดไม่ถึงว่าจะวางปลายแขนด้วยความแม่นยำ จำกัด ในความคิดของฉันเป็นคำอธิบายที่ลึกซึ้งกว่าคำที่ได้รับการยอมรับและยังเป็นคำอธิบายที่มี echos ใน nan! = nan rule
Paul Panzer

3
C99 ระบุว่าประเภทจุดลอยตัวจริงไม่ได้รับการเลื่อนระดับเป็นเชิงซ้อนเมื่อคูณด้วยประเภทที่ซับซ้อน (มาตรา 6.3.1.8 ของมาตรฐานฉบับร่าง) และเท่าที่ฉันรู้ว่าสิ่งเดียวกันนี้เป็นจริงกับ std :: complex ของ C ++ ซึ่งหมายความว่า 1 คือเอกลักษณ์ที่ทวีคูณสำหรับประเภทเหล่านั้นในภาษาเหล่านั้น Python ควรทำเช่นเดียวกัน ฉันจะเรียกพฤติกรรมปัจจุบันว่าเป็นเพียงข้อบกพร่อง
benrg

2
@PaulPanzer: ฉันไม่ทำ แต่แนวคิดพื้นฐานคือศูนย์หนึ่ง (ซึ่งฉันจะเรียกว่า Z) จะรักษา x + Z = x และ x * Z = Z เสมอและ 1 / Z = NaN หนึ่ง (บวก infinitesimal) จะรักษา 1 / P = + INF หนึ่ง (ลบน้อยที่สุด) จะรักษา 1 / N = -INF และ (ไม่ได้ลงนามน้อยที่สุด) จะให้ 1 / U = NaN โดยทั่วไป xx จะเป็น U เว้นแต่ x จะเป็นจำนวนเต็มจริงซึ่งในกรณีนี้จะให้ผลลัพธ์เป็น Z
supercat

6

นี่คือรายละเอียดการใช้งานเกี่ยวกับการใช้การคูณที่ซับซ้อนใน CPython แตกต่างจากภาษาอื่น ๆ (เช่น C หรือ C ++) CPython ใช้วิธีที่ค่อนข้างง่าย:

  1. ints / float ได้รับการเลื่อนระดับเป็นจำนวนเชิงซ้อนในการคูณ
  2. มีการใช้สูตรโรงเรียนอย่างง่ายซึ่งไม่ได้ให้ผลลัพธ์ที่ต้องการ / คาดหวังทันทีที่เกี่ยวข้องกับตัวเลขที่ไม่มีที่สิ้นสุด:
Py_complex
_Py_c_prod(Py_complex a, Py_complex b)
{
    Py_complex r;
    r.real = a.real*b.real - a.imag*b.imag;
    r.imag = a.real*b.imag + a.imag*b.real;
    return r;
}

กรณีหนึ่งที่มีปัญหากับรหัสด้านบนคือ:

(0.0+1.0*j)*(inf+inf*j) = (0.0*inf-1*inf)+(0.0*inf+1.0*inf)j
                        =  nan + nan*j

อย่างไรก็ตามหนึ่งต้องการ-inf + inf*jผล

ในแง่นี้ภาษาอื่น ๆ ก็อยู่ไม่ไกล: การคูณจำนวนเชิงซ้อนนั้นไม่ได้เป็นส่วนหนึ่งของมาตรฐาน C มาเป็นเวลานานซึ่งรวมอยู่ใน C99 เป็นภาคผนวก G เท่านั้นซึ่งอธิบายถึงวิธีการคูณที่ซับซ้อน - และไม่ง่ายอย่างที่คิด สูตรโรงเรียนข้างต้น! มาตรฐาน C ++ ไม่ได้ระบุวิธีการทำงานของการคูณที่ซับซ้อนดังนั้นการใช้งานคอมไพเลอร์ส่วนใหญ่จะกลับไปใช้งาน C ซึ่งอาจเป็นไปตาม C99 (gcc, clang) หรือไม่ (MSVC)

สำหรับตัวอย่าง "ที่เป็นปัญหา" ข้างต้นการใช้งานที่สอดคล้องกับ C99 (ซึ่งซับซ้อนกว่าสูตรของโรงเรียน) จะให้ผลลัพธ์ที่คาดหวัง( ดูสด ):

(0.0+1.0*j)*(inf+inf*j) = -inf + inf*j 

แม้ว่าจะใช้มาตรฐาน C99 แต่ก็ไม่ได้กำหนดผลลัพธ์ที่ชัดเจนสำหรับอินพุตทั้งหมดและอาจแตกต่างกันแม้ในเวอร์ชันที่รองรับ C99

ผลข้างเคียงอีกประการหนึ่งของการfloatไม่ได้รับการโปรโมตcomplexใน C99 คือการคูณinf+0.0jด้วย1.0หรือ1.0+0.0jสามารถนำไปสู่ผลลัพธ์ที่แตกต่างกัน (ดูที่นี่สด):

  • (inf+0.0j)*1.0 = inf+0.0j
  • (inf+0.0j)*(1.0+0.0j) = inf-nanjส่วนจินตภาพเป็น-nanและไม่ใช่nan(สำหรับ CPython) จะไม่มีบทบาทที่นี่เพราะ nans ที่เงียบทั้งหมดมีค่าเท่ากัน (ดูสิ่งนี้ ) แม้บางส่วนจะมีการตั้งค่าบิตเครื่องหมาย (และพิมพ์เป็น "-" ให้ดูสิ่งนี้ ) และบางส่วนไม่

ซึ่งอย่างน้อยก็ตอบโต้ได้ง่าย


กุญแจสำคัญของฉันที่นำออกไปจากมันคือไม่มีอะไรง่าย ๆ เกี่ยวกับการคูณ (หรือหาร) จำนวนเชิงซ้อน "ง่ายๆ" และเมื่อสลับระหว่างภาษาหรือแม้แต่คอมไพเลอร์เราต้องรั้งตัวเองเพื่อหาจุดบกพร่อง / ความแตกต่างที่ละเอียดอ่อน


ฉันรู้ว่ามีรูปแบบนาโนบิตมากมาย ไม่ทราบว่าสัญญาณบิตแม้ว่า แต่ฉันหมายถึงความหมาย - แนนแตกต่างจากแนนอย่างไร? หรือฉันควรจะพูดว่าแนนต่างจากแนน?
Paul Panzer

@PaulPanzer นี่เป็นเพียงรายละเอียดการใช้งานของวิธีการprintfและการทำงานที่คล้ายกันกับ double: พวกเขาดูที่ sign-bit เพื่อตัดสินใจว่าควรพิมพ์ "-" หรือไม่ (ไม่ว่าจะเป็น nan หรือไม่ก็ตาม) คุณพูดถูกไม่มีความแตกต่างที่มีความหมายระหว่าง "nan" และ "-nan" แก้ไขคำตอบส่วนนี้ในไม่ช้า
ead

ก็ดี. เป็นกังวลสำหรับโมว่าทุกสิ่งที่ฉันคิดว่าฉันรู้เกี่ยวกับ fp นั้นไม่ถูกต้องจริงๆ ...
Paul Panzer

ขออภัยที่ทำให้รำคาญ แต่คุณแน่ใจหรือไม่ว่านี่"ไม่มี 1.0 ในจินตนาการนั่นคือ 1.0j ซึ่งไม่เหมือนกับ 0.0 + 1.0j เมื่อเทียบกับการคูณ" ถูกต้อง? ภาคผนวก G นั้นดูเหมือนจะระบุประเภทจินตภาพล้วน ๆ (G.2) และกำหนดว่าควรคูณอย่างไรเป็นต้น (G.5.1)
Paul Panzer

@PaulPanzer ไม่ขอบคุณที่ชี้ประเด็น! ในฐานะ c ++ - coder ส่วนใหญ่ฉันเห็น C99-standard ผ่าน C ++ - glases - มันทำให้ความคิดของฉันลื่นไถลนั่นคือ C ก้าวไปข้างหน้าที่นี่ - คุณพูดถูกอีกครั้ง
ead

3

คำจำกัดความตลก ๆ จาก Python หากเราแก้ปัญหานี้ด้วยปากกาและกระดาษฉันจะบอกว่าผลลัพธ์ที่คาดหวังจะเป็นไปexpected: (inf + 0j)ตามที่คุณชี้ให้เห็นเพราะเรารู้ว่าเราหมายถึงบรรทัดฐานของ1สิ่งนั้น(float('inf')+0j)*1 =should= ('inf'+0j):

แต่นั่นไม่ใช่อย่างที่คุณเห็น ... เมื่อเราเรียกใช้เราจะได้รับ:

>>> Complex( float('inf') , 0j ) * 1
result: (inf + nanj)

Python เข้าใจว่านี่*1เป็นจำนวนเชิงซ้อนไม่ใช่บรรทัดฐาน1ดังนั้นจึงตีความเป็น*(1+0j)และข้อผิดพลาดจะปรากฏขึ้นเมื่อเราพยายามทำinf * 0j = nanjตามที่inf*0ไม่สามารถแก้ไขได้

สิ่งที่คุณต้องการทำจริงๆ (สมมติว่า 1 เป็นบรรทัดฐานของ 1):

จำไว้ว่าถ้าz = x + iyเป็นจำนวนเชิงซ้อนที่มีส่วนจริง x และส่วนจินตภาพ y คอนจูเกตเชิงซ้อนของzจะถูกกำหนดเป็นz* = x − iyและค่าสัมบูรณ์หรือที่เรียกว่า the norm of zถูกกำหนดให้เป็น:

ป้อนคำอธิบายภาพที่นี่

สมมติว่า1เป็นบรรทัดฐานที่1เราควรทำสิ่งต่างๆเช่น:

>>> c_num = complex(float('inf'),0)
>>> value = 1
>>> realPart=(c_num.real)*value
>>> imagPart=(c_num.imag)*value
>>> complex(realPart,imagPart)
result: (inf+0j)

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

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