ทำไมไม่มีตัวดำเนินการพลังงานใน Java / C ++


23

ในขณะที่มีโอเปอเรเตอร์ดังกล่าว - **ใน Python ฉันสงสัยว่าทำไม Java และ C ++ จึงไม่มีตัวนี้เช่นกัน

มันง่ายที่จะสร้างคลาสที่คุณกำหนดใน C ++ พร้อมกับโอเปอเรเตอร์การบรรทุกเกินพิกัด (และฉันเชื่อว่ามันเป็นไปได้ใน Java) แต่เมื่อพูดถึงประเภทดั้งเดิมเช่น int, double และอื่น ๆ คุณจะต้องใช้ไลบรารี่ ฟังก์ชั่นเช่นMath.power(และมักจะต้องร่ายทั้งสองครั้ง)

ดังนั้น - ทำไมไม่กำหนดผู้ประกอบการดังกล่าวสำหรับประเภทดั้งเดิม?


8
ใน C ++ เราไม่สามารถสร้างโอเปอเรเตอร์ของเราเองได้ คุณสามารถโอเวอร์โหลดโอเปอเรเตอร์ที่มีอยู่เท่านั้น

1
@Mahesh ดังนั้นฉันสามารถสร้างคลาส Number ของฉันเองและโอเปอเรเตอร์โอเวอร์โหลด ^ เป็นพลังงาน ความจริงนั้นไม่ได้เกี่ยวข้อง

22
@RanZilber: มันมีความสำคัญเนื่องจากความสำคัญของ^ผู้ประกอบการไม่ตรงกับความสำคัญของการยกกำลัง a + b ^ cพิจารณาการแสดงออก ในวิชาคณิตศาสตร์การยกกำลังจะดำเนินการเป็นอันดับแรก ( b ^ c) จากนั้นจะเพิ่มกำลังที่aได้ ใน C ++ นอกจากนี้จะดำเนินการเป็นครั้งแรก ( a + b) จากนั้นผู้ประกอบการจะดำเนินการกับ^ cดังนั้นแม้ว่าคุณจะใช้งาน^โอเปอเรเตอร์เพื่อหมายถึงการยกกำลัง แต่ความสำคัญก็จะทำให้ทุกคนประหลาดใจ
ใน silico

2
@RamZilber - ^เป็น XOR ใน C ++ ขอแนะนำว่าตัวดำเนินการที่โอเวอร์โหลดไม่ควรแตกต่างจากชนิดข้อมูลดั้งเดิมที่ใช้

4
@RanZilber: เพราะมันไม่ได้ใช้งานง่ายเลยที่จะใช้โอเปอเรเตอร์ที่คุณพูดถึงหมายถึงการยกกำลัง ฉันจะตั้งคำถามอย่างจริงจังถึงความสามารถของโปรแกรมเมอร์ C ++ ที่เกินจำนวน++ผู้ปฏิบัติงานหรือ!ผู้ปฏิบัติงานเป็นต้น อัล หมายถึงการยกกำลัง แต่คุณทำไม่ได้เพราะผู้ดำเนินการที่คุณพูดคุยยอมรับเพียงข้อโต้แย้งเดียว การยกกำลังต้องการสองอาร์กิวเมนต์
ใน silico

คำตอบ:


32

โดยทั่วไปแล้วตัวดำเนินการดั้งเดิมใน C (และโดยการขยาย C ++) ได้รับการออกแบบให้สามารถใช้งานได้โดยฮาร์ดแวร์อย่างง่ายในคำสั่งเดียว สิ่งที่ต้องการยกกำลังมักต้องการการสนับสนุนซอฟต์แวร์ ดังนั้นจึงไม่ได้มีตามค่าเริ่มต้น

std::powนอกจากนี้ก็มีให้โดยไลบรารีมาตรฐานของภาษาในรูปแบบของ

ในที่สุดการทำเช่นนี้สำหรับประเภทข้อมูลจำนวนเต็มจะไม่สมเหตุสมผลนักเนื่องจากค่าที่น้อยที่สุดสำหรับการยกกำลังจะทำให้ช่วงที่จำเป็นต้องมีสำหรับ int มีค่าสูงสุด 65,535 แน่นอนว่าคุณสามารถทำสิ่งนี้เพื่อเพิ่มเป็นสองเท่าและลอยตัว แต่ไม่ใช่ ints แต่ทำไมภาษาจึงไม่สอดคล้องกับคุณลักษณะที่ไม่ค่อยได้ใช้


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

@Sion: อย่างน้อยใน x86 โมดูลัสเป็นคำสั่งเดียว ( DIVทั้งการหารและโมดูลัส) คุณได้รับฉันในจุดที่สอดคล้องกันว่า
Billy ONeal

@Billy ONeal: จุดโมดูลัสลอยในคำสั่งเดียว? ฉันไม่ได้เข้าไปพัวพันกับการชุมนุมเมื่อถึงปลายปีเพื่อทราบตัวเอง หากเป็นเช่นนั้นผู้ดำเนินการโมดูลัสควรใช้กับประเภทจุดลอย

3
@ DonalFellows: FORTRAN มีโอเปอเรเตอร์การยกกำลังนานก่อนที่มันจะมีอะไรที่คล้ายกับการรองรับบิกุ่ม
supercat

1
@ DonalFellows: ผู้ให้บริการพลังงานไม่เป็นประโยชน์กับจำนวนเต็มเหมือนกับการลอยตัว แต่สำหรับพลังขนาดเล็ก (โดยเฉพาะการยกกำลังสอง) มันสามารถใช้งานได้อย่างแน่นอน โดยส่วนตัวแล้วฉันชอบวิธีที่จะทำให้ผู้ปฏิบัติงานหลุดจากตัวอักษร (เหมือนกับที่ Pascal ทำกับdivหรือ FORTRAN ด้วย.EQ.); ขึ้นอยู่กับกฎช่องว่างของภาษามันอาจเป็นไปได้ที่จะมีจำนวนผู้ประกอบการโดยพลการโดยไม่ต้องให้พวกเขาเป็นคำสงวน
supercat

41

คำถามนี้ตอบได้สำหรับ C ++: Stroustrup, "การออกแบบและวิวัฒนาการของ C ++" กล่าวถึงเรื่องนี้ในหัวข้อ 11.6.1, pp. 247-250

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

ไม่มีตัวเลือกที่ดีสำหรับโอเปอเรเตอร์ ^เป็นพิเศษหรือและ^^ความสับสนได้รับเชิญเพราะความสัมพันธ์ระหว่าง&และ|และและ && ไม่เหมาะสมเนื่องจากจะมีแนวโน้มเป็นธรรมชาติที่จะเขียนเพื่อยกกำลังของมูลค่าที่มีอยู่และที่ได้รับแล้ว สิ่งที่ดีที่สุดอาจเป็นได้ซึ่งดูเหมือนว่าไม่มีใครชอบจริง ๆ||!!=*^

Stroustrup พิจารณา**อีกครั้ง แต่มันมีอยู่แล้วมีความหมายใน C: a**pเป็นaครั้งสิ่งที่pชี้ไปและchar ** c;ประกาศเป็นตัวชี้ที่จะชี้ไปยังc charการแนะนำ**เป็นโทเค็นหมายถึง "การประกาศของตัวชี้ไปยังตัวชี้ไปยัง", "คูณสิ่งต่อไปที่ชี้ไปที่" (ถ้าเป็นตัวชี้) หรือ "การยกกำลัง" (ถ้าตามด้วยตัวเลข) ทำให้เกิดปัญหาที่สำคัญกว่า a/b**pจะต้องแยกวิเคราะห์ราวกับa/(b**p)ว่า p เป็นตัวเลข แต่(a/b) * *pถ้า p เป็นตัวชี้ดังนั้นสิ่งนี้จะต้องได้รับการแก้ไขในตัวแยกวิเคราะห์

มันอาจจะเป็นไปได้ แต่มันจะมีความซับซ้อนของตารางนำหน้าและตัวแยกวิเคราะห์และทั้งคู่ก็ซับซ้อนเกินไป

ฉันไม่รู้เรื่องราวเกี่ยวกับ Java; ทั้งหมดที่ฉันทำได้ก็คือเก็งกำไร ในฐานะที่เป็นสำหรับ C ซึ่งจะเริ่มดำเนินการ C ทั้งหมดจะถูกแปลได้อย่างง่ายดายในรหัสการชุมนุมส่วนหนึ่งที่จะลดความซับซ้อนของคอมไพเลอร์และอีกส่วนหนึ่งเพื่อหลีกเลี่ยงการหลบซ่อนตัวฟังก์ชั่นใช้เวลานานในการประกอบง่าย (ความจริงที่ว่าoperator+()และคนอื่น ๆ สามารถซ่อนความซับซ้อนและประสิทธิภาพการทำงานที่ดีฮิตเป็นหนึ่ง ของการร้องเรียนก่อนหน้านี้เกี่ยวกับ C ++)


2
คำตอบที่ดี ฉันเดาว่า Java พยายามทำให้ C ง่ายขึ้นในแง่นี้ดังนั้นจึงไม่มีใครต้องการเพิ่มผู้ดำเนินการใหม่ *^นั่นเป็นที่น่าเสียดายที่ไม่มีใครถามผมผมก็จะชอบ : D
maaartinus

1
C ถูกสร้างขึ้นเพื่อทำการจัดรูปแบบข้อความ Fortran ถูกสร้างขึ้นเพื่อทำคณิตศาสตร์และมีคณิตศาสตร์ที่ซับซ้อนพลังงานและเมทริกซ์เมื่อ 20 ปีก่อน
Martin Beckett

@Martin Beckett: คุณพบหลักฐานที่ C ถูกสร้างขึ้นสำหรับการจัดรูปแบบข้อความ? สำหรับฉันแล้วมันเป็นภาษาที่ค่อนข้างงุ่มง่ามและสิ่งที่ฉันได้อ่านเกี่ยวกับต้นกำเนิดของ C บอกว่ามันถูกออกแบบมาสำหรับการเขียนโปรแกรมระบบสำหรับ Unix เป็นหลัก
David Thornley

@DavidThornley - มันถูกออกแบบมาเพื่อเขียน Unix แต่การใช้ Unix ในยุคแรกดูเหมือนว่าจะเป็นการจัดรูปแบบข้อความและถึงเวลาที่มันจะมีสตริงและไลบรารี่ i / o ที่กว้างขวาง
Martin Beckett

6
+1: ความหมายที่มีอยู่a**pคือฆาตกร (แฮ็กที่จะแก้ไขปัญหาที่เกิดขึ้น… Brr!)
Donal Fellows

13

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



3
ฉันจะใช้x**2และx**3ไม่ว่าจะไม่ค่อย และการใช้เวทย์มนตร์ธารที่คอมไพเลอร์รู้และปรับให้เหมาะกับกรณีง่าย ๆ น่าจะดี
CodesInChaos

2
@CodeInChaos: อย่างไรก็ตามx * xและx * x * xไม่ใช่สิ่งทดแทนที่ไม่ดีสำหรับสแควร์และคิวบ์
David Thornley

5
@ David คุณไม่สามารถเขียนได้x*xถ้า x เป็นนิพจน์ ในกรณีที่ดีที่สุดรหัสจะกลายเป็นเทอะทะและในที่สุดช้าหรือผิด ดังนั้นคุณต้องกำหนดฟังก์ชั่นสแควร์และคิวบ์ของคุณเอง และยิ่งไปกว่านั้นรหัสก็น่าเกลียดกว่าการใช้ ** เป็นตัวดำเนินการพลังงาน
CodesInChaos

1
@ David ฉันต้องใส่วงเล็บใช่ แต่ไม่จำเป็นต้องทำซ้ำการแสดงออกหลายครั้งและ bloats ซอร์สโค้ด ซึ่งช่วยลดความสามารถในการอ่านได้มาก และการกำจัด subexpression ทั่วไปนั้นเป็นไปได้ก็ต่อเมื่อคอมไพเลอร์สามารถรับประกันการแสดงออกว่าปราศจากผลข้างเคียง และอย่างน้อยที่สุด. กระวนกระวายใจสุทธิไม่ได้ฉลาดเกินไปในเรื่องนั้น
CodesInChaos

11

นักออกแบบภาษาจาวาและไลบรารีหลักตัดสินใจที่จะลดการดำเนินการทางคณิตศาสตร์ส่วนใหญ่ให้กับชั้นเรียนคณิตศาสตร์ ดูMath.pow ()

ทำไม? ความยืดหยุ่นในการจัดลำดับความสำคัญของประสิทธิภาพด้วยความแม่นยำแบบบิตต่อบิต มันจะขัดกับส่วนที่เหลือของข้อกำหนดภาษาที่จะบอกว่าพฤติกรรมของผู้ประกอบการทางคณิตศาสตร์ในตัวอาจแตกต่างจากแพลตฟอร์มไปยังแพลตฟอร์มในขณะที่ระดับคณิตศาสตร์ระบุว่าพฤติกรรมที่อาจเสียสละความแม่นยำสำหรับการปฏิบัติงานดังนั้นผู้ซื้อระวัง:

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


6

การยกกำลังเป็นส่วนหนึ่งของ Fortran ตั้งแต่เริ่มต้นเพราะมีจุดมุ่งหมายอย่างเต็มที่ในการเขียนโปรแกรมทางวิทยาศาสตร์ วิศวกรและนักฟิสิกส์ใช้บ่อยครั้งในการจำลองเนื่องจากความสัมพันธ์ของกฎพลังงานเป็นเรื่องธรรมดาในฟิสิกส์

Python มีสถานะที่แข็งแกร่งในการคำนวณทางวิทยาศาสตร์เช่นกัน (NumPy และ SciPy) พร้อมกับผู้ประกอบการยกกำลังของมันชี้ให้เห็นว่ามันมีวัตถุประสงค์เพื่อการเขียนโปรแกรมทางวิทยาศาสตร์เช่นกัน

C, Java และ C # มีรากฐานในการเขียนโปรแกรมระบบ บางทีนั่นอาจเป็นอิทธิพลที่ทำให้ไม่ต้องยกกำลังออกจากกลุ่มผู้ให้บริการที่รองรับ

เพียงทฤษฎี


4

C ผู้ประกอบการที่กำหนดไว้เท่านั้นสำหรับการดำเนินการทางคณิตศาสตร์ที่พบบ่อยสอดคล้องกับ ALU เป้าหมายหลักคือการสร้างอินเทอร์เฟซที่มนุษย์สามารถอ่านได้เพื่อประกอบโค้ด

C ++ ไม่ได้เปลี่ยนพฤติกรรมของตัวดำเนินการใด ๆ เพราะต้องการให้รหัสฐานทั้งหมดที่เขียนใน C เป็นไปตามมาตรฐาน

Java ทำเช่นเดียวกันเพราะไม่ต้องการข่มขู่โปรแกรมเมอร์ C ++ ที่มีอยู่


เมื่อ C ถูกสร้างขึ้นการคูณและการหารไม่ได้ขาดบ่อยในฮาร์ดแวร์และจะต้องมีการใช้งานในซอฟต์แวร์ แต่ C มีตัวคูณและตัวหาร
siride

@siride: สำหรับความรู้ของฉัน PDP-7 คอมพิวเตอร์เครื่องแรกที่รัน Unix นั้นมีการคูณฮาร์ดแวร์และการหารผ่าน EAE โปรดดู: bitsavers.org/pdf/dec/pdp7/F-75_PDP-7userHbk_Jun65.pdf
Tugrul Ates

1

เป็นอย่างดีเพราะผู้ให้บริการทุกรายที่ใช้พลังงานอย่างมีประสิทธิภาพนั้นมีอยู่แล้ว ^ is XOR และ ** กำหนดตัวชี้ไปยังตัวชี้ ดังนั้นแทนที่จะมีฟังก์ชั่นที่ทำสิ่งเดียวกัน (เช่น pow ())


@RTS - นักพัฒนาซอฟต์แวร์ที่เป็นคนมองโลกในแง่ดีมีประสิทธิภาพมากกว่าหรือไม่?

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

@RTS: pow()ฟังก์ชั่นทำการคำนวณ ณ รันไทม์เว้นแต่คุณจะมีคอมไพเลอร์ที่สามารถทำการพับแบบคงpow()ที่ซึ่งฉันสงสัยอย่างมาก (คอมไพเลอร์บางตัวมีตัวเลือกให้คุณใช้ตัวประมวลผลภายในเพื่อทำการคำนวณ)
ใน silico

@ ใน silico ฉันไม่ได้หมายความว่ามันคำนวณค่าสุดท้ายฉันหมายความว่าคอมไพเลอร์จะปรับการเรียกฟังก์ชันให้เหมาะสมดังนั้นคุณแค่มีสมการดิบ

2
@ Josefx: แน่นอนว่าเป็นเหตุผลที่ดี ซิงเกิล*นั้นเป็นโทเค็นของคำศัพท์ไม่ว่าจะใช้สำหรับการอ้อมหรือการคูณ การ**ยกกำลังความหมายอาจเป็นโทเค็นคำศัพท์หนึ่งหรือสองภาษาและคุณไม่ต้องการให้ lexer ของคุณกดปุ่มสัญลักษณ์เพื่อโทเค็น
David Thornley

0

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

c = a + b;
// equals
c.set(a.add(b));
// or as free functions
set(c, add(a,b));

มันละเอียดมากขึ้นดังนั้นฉันจึงเห็นอะไรผิดปกติกับการใช้ฟังก์ชั่นในการแสดง 'พลังของ'


-1

การบวก / การลบ / การปฏิเสธและการคูณ / การหารเป็นตัวดำเนินการทางคณิตศาสตร์ขั้นพื้นฐาน ถ้าคุณจะทำให้พลังงานเป็นผู้ดำเนินการคุณจะหยุดที่ไหน ผู้ประกอบการรากที่สอง? ตัวดำเนินการ N-root ผู้ประกอบการลอการิทึม?

ฉันไม่สามารถพูดกับผู้สร้างของพวกเขา แต่ฉันสามารถพูดได้ว่าฉันคิดว่ามันกลายเป็นเรื่องเทอะทะและไม่ใช่มุมฉากที่จะมีตัวดำเนินการดังกล่าวในภาษา จำนวนอักขระที่ไม่ใช่ตัวอักษร / ตัวเลข / ช่องว่างที่เหลืออยู่บนแป้นพิมพ์นั้นค่อนข้าง จำกัด มันแปลกที่มีตัวดำเนินการโมดูลัสใน C ++


+1 - ฉันไม่เห็นว่าทำไมการmodเป็นผู้ดำเนินการจึงแปลก มันมักจะเป็นคำสั่งเดียว มันเป็นการดำเนินการดั้งเดิมกับจำนวนเต็ม มันถูกใช้มากที่สุดในสาขาวิทยาศาสตร์คอมพิวเตอร์ (การใช้สิ่งต่าง ๆ เช่นบัฟเฟอร์ที่ไม่มีขอบเขตmodจะเหม็น)
Billy ONeal

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