ควรใช้ <หรือ <= ใน for loop [closed]


124

ถ้าคุณต้องวนซ้ำ 7 ครั้งคุณจะใช้:

for (int i = 0; i < 7; i++)

หรือ:

for (int i = 0; i <= 6; i++)

มีข้อควรพิจารณาสองประการ:

  • ประสิทธิภาพ
  • การอ่าน

สำหรับประสิทธิภาพฉันสมมติว่าเป็น Java หรือ C # มีความสำคัญหรือไม่ว่าจะใช้ "น้อยกว่า" หรือ "น้อยกว่าหรือเท่ากับ"? หากคุณมีข้อมูลเชิงลึกสำหรับภาษาอื่นโปรดระบุว่า

เพื่อความสามารถในการอ่านฉันสมมติว่าอาร์เรย์ที่ใช้ 0

UPD: การพูดถึงอาร์เรย์ที่ใช้ 0 ของฉันอาจทำให้สับสน ฉันไม่ได้พูดถึงการทำซ้ำผ่านองค์ประกอบอาร์เรย์ เพียงแค่วนรอบทั่วไป

มีจุดดีด้านล่างเกี่ยวกับการใช้ค่าคงที่ซึ่งจะอธิบายได้ว่าเลขวิเศษนี้คืออะไร ดังนั้นถ้าฉันมี " int NUMBER_OF_THINGS = 7" แล้ว " i <= NUMBER_OF_THINGS - 1" จะดูแปลก ๆ ใช่ไหม


ฉันจะบอกว่า: ถ้าคุณเรียกใช้อาร์เรย์ทั้งหมดอย่าลบหรือเพิ่มตัวเลขใด ๆ ทางด้านซ้าย
Letterman

คำตอบ:


287

เป็นครั้งแรกที่มีมากขึ้นเป็นสำนวน โดยเฉพาะอย่างยิ่งมันระบุ (ในความหมายที่อิง 0) จำนวนการทำซ้ำ เมื่อใช้สิ่งที่ 1-based (เช่น JDBC, IIRC) ฉันอาจถูกล่อลวงให้ใช้ <= ดังนั้น:

for (int i=0; i < count; i++) // For 0-based APIs

for (int i=1; i <= count; i++) // For 1-based APIs

ฉันคาดหวังว่าความแตกต่างของประสิทธิภาพจะน้อยมากในโค้ดในโลกแห่งความเป็นจริง


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

3
คุณจะพิจารณาใช้! = แทนหรือไม่? ฉันบอกว่าสิ่งที่ชัดเจนที่สุดกำหนดให้ฉันเป็นตัวนับลูปและไม่มีอะไรอื่น
yungchin

21
ฉันมักจะไม่ มันไม่คุ้นเคยเกินไป นอกจากนี้ยังเสี่ยงต่อการวนซ้ำที่ยาวมากหากมีคนเพิ่มฉันโดยไม่ได้ตั้งใจระหว่างลูป
Jon Skeet

5
การเขียนโปรแกรมทั่วไปด้วยตัวทำซ้ำ STL กำหนดให้ใช้! =. มัน (การเพิ่มขึ้นสองครั้งโดยไม่ได้ตั้งใจ) ไม่ได้เป็นปัญหาสำหรับฉัน ฉันยอมรับว่าสำหรับดัชนี <(หรือ> จากมากไปหาน้อย) มีความชัดเจนและเป็นแบบแผนมากขึ้น
Jonathan Graehl

2
โปรดจำไว้ว่าหากคุณวนลูปตามความยาวของอาร์เรย์โดยใช้ <JIT จะปรับการเข้าถึงอาร์เรย์ให้เหมาะสม (ลบการตรวจสอบที่ถูกผูกไว้) ดังนั้นควรจะเร็วกว่าที่ใช้ <=. ฉันยังไม่ได้ตรวจสอบ
กำหนดค่า

72

ลูปทั้งสองนั้นวนซ้ำ 7 ครั้ง ฉันจะบอกว่าอันที่มี 7 อยู่นั้นอ่านได้ / ชัดเจนกว่าเว้นแต่คุณจะมีเหตุผลที่ดีจริงๆ


ฉันจำได้ว่าตอนที่ฉันเริ่มเรียนภาษาจาวาครั้งแรก ฉันเกลียดแนวคิดของดัชนีที่อิง 0 เพราะฉันใช้ดัชนี 1 ฐานมาโดยตลอด ดังนั้นฉันจะใช้ตัวแปร <= 6 เสมอ (ดังที่แสดงในคำถาม) สำหรับความเสียหายของฉันเองเพราะมันจะทำให้ฉันสับสนมากขึ้นในที่สุดเมื่อลูปออกจริง ง่ายกว่าเพียงใช้ <
James Haug

55

ฉันจำได้ว่าตั้งแต่สมัยที่เราทำ 8086 Assembly ที่วิทยาลัยมันเป็นเรื่องที่ต้องทำมากกว่า:

for (int i = 6; i > -1; i--)

เนื่องจากมีการดำเนินการJNSซึ่งหมายถึง Jump if No Sign การใช้สิ่งนี้หมายความว่าไม่มีการค้นหาหน่วยความจำหลังจากแต่ละรอบเพื่อให้ได้ค่าเปรียบเทียบและไม่มีการเปรียบเทียบ ทุกวันนี้คอมไพเลอร์ส่วนใหญ่ปรับการใช้งานรีจิสเตอร์ให้เหมาะสมเพื่อให้หน่วยความจำไม่สำคัญอีกต่อไป แต่คุณยังคงได้รับการเปรียบเทียบที่ไม่จำเป็น

วิธีการใส่ 7 หรือ 6 ในลูปของคุณคือการแนะนำ " หมายเลขวิเศษ " เพื่อให้อ่านง่ายขึ้นคุณควรใช้ค่าคงที่กับชื่อเปิดเผยเจตนา แบบนี้:

const int NUMBER_OF_CARS = 7;
for (int i = 0; i < NUMBER_OF_CARS; i++)

แก้ไข: ผู้คนไม่ได้รับสิ่งที่ประกอบดังนั้นจึงจำเป็นต้องมีตัวอย่างที่สมบูรณ์กว่า:

ถ้าเราทำเพื่อ (i = 0; i <= 10; i ++) คุณต้องทำสิ่งนี้:

    mov esi, 0
loopStartLabel:
                ; Do some stuff
    inc esi
                ; Note cmp command on next line
    cmp esi, 10
    jle exitLoopLabel
    jmp loopStartLabel
exitLoopLabel:

ถ้าเราทำเพื่อ (int i = 10; i> -1; i--) คุณจะได้รับสิ่งนี้:

    mov esi, 10
loopStartLabel:
                ; Do some stuff
    dec esi
                ; Note no cmp command on next line
    jns exitLoopLabel
    jmp loopStartLabel
exitLoopLabel:

ฉันเพิ่งตรวจสอบและคอมไพเลอร์ C ++ ของ Microsoft ไม่ได้ทำการเพิ่มประสิทธิภาพนี้ แต่จะทำหากคุณทำ:

for (int i = 10; i >= 0; i--) 

ดังนั้นคุณธรรมคือถ้าคุณใช้ Microsoft C ++ †และการขึ้นหรือลงจะไม่แตกต่างกันเพื่อให้ได้ลูปอย่างรวดเร็วคุณควรใช้:

for (int i = 10; i >= 0; i--)

แทนที่จะเป็นอย่างใดอย่างหนึ่งต่อไปนี้:

for (int i = 10; i > -1; i--)
for (int i = 0; i <= 10; i++)

แต่การได้รับความสามารถในการอ่าน "for (int i = 0; i <= 10; i ++)" อย่างตรงไปตรงมานั้นมีความสำคัญมากกว่าคำสั่งตัวประมวลผลที่ขาดหายไป

†คอมไพเลอร์อื่น ๆ อาจทำสิ่งที่แตกต่างกัน


4
กรณี "magic number" แสดงให้เห็นอย่างชัดเจนเหตุใดจึงควรใช้ <กว่า <=
Rene Saarsoo

11
อีกเวอร์ชันหนึ่งคือ "for (int i = 10; i--;)" บางคนใช้ "for (int i = 10; i -> 0;)" และหลอกว่าชุดค่าผสม -> ไปที่
Zayenz

2
+1 สำหรับรหัสประกอบ
neuro

1
แต่เมื่อถึงเวลาที่ต้องใช้ตัวนับลูปเช่นสำหรับการจัดทำดัชนีอาร์เรย์คุณจะต้องทำ7-iสิ่งนี้เพื่อล้นการเพิ่มประสิทธิภาพใด ๆ ที่คุณได้รับจากการนับถอยหลัง
Lie Ryan

@Lie ใช้เฉพาะในกรณีที่คุณต้องการดำเนินการตามลำดับ ด้วยการดำเนินการส่วนใหญ่ในลูปประเภทนี้คุณสามารถนำไปใช้กับรายการในลูปตามลำดับที่คุณต้องการ ตัวอย่างเช่นหากคุณกำลังค้นหาค่าก็ไม่สำคัญว่าคุณจะเริ่มต้นที่ส่วนท้ายของรายการและทำงานหรือเมื่อเริ่มรายการและหยุดทำงาน (สมมติว่าคุณไม่สามารถคาดเดาได้ว่าจะสิ้นสุดรายการใด ดูเหมือนว่าจะเป็นและการแคชหน่วยความจำไม่ใช่ปัญหา)
Martin Brown

27

ฉันใช้ <array.length เสมอเพราะอ่านง่ายกว่า <= array.length-1

นอกจากนี้ยังมี <7 และเนื่องจากคุณรู้ว่ามันเริ่มต้นด้วยดัชนี 0 มันควรจะเข้าใจง่ายว่าตัวเลขคือจำนวนการวนซ้ำ


คุณควรระมัดระวังในการตรวจสอบต้นทุนของฟังก์ชัน Length เมื่อใช้งานแบบวนซ้ำ ตัวอย่างเช่นหากคุณใช้ strlen ใน C / C ++ คุณจะต้องเพิ่มเวลาในการเปรียบเทียบอย่างมหาศาล เนื่องจาก strlen ต้องวนซ้ำทั้งสตริงเพื่อค้นหาคำตอบซึ่งเป็นสิ่งที่คุณอาจต้องการทำเพียงครั้งเดียวแทนที่จะทำซ้ำทุกครั้งของลูป
Martin Brown

2
@Martin Brown: ใน Java (และฉันเชื่อว่า C #), String.length และ Array.length เป็นค่าคงที่เนื่องจาก String ไม่เปลี่ยนรูปและ Array มีความยาวไม่เปลี่ยนรูป และเนื่องจาก String.length และ Array.length เป็นฟิลด์ (แทนการเรียกใช้ฟังก์ชัน) คุณจึงมั่นใจได้ว่าต้องเป็น O (1) ในกรณีของ C ++ ทำไมคุณถึงใช้ C-string ตั้งแต่แรก?
Lie Ryan

18

เห็นได้จากมุมมองการเพิ่มประสิทธิภาพมันไม่สำคัญ

เห็นได้จากมุมมองรูปแบบโค้ดฉันชอบ <. เหตุผล:

for ( int i = 0; i < array.size(); i++ )

อ่านได้ง่ายกว่า

for ( int i = 0; i <= array.size() -1; i++ )

ยัง <ให้จำนวนการทำซ้ำทันที

อีกโหวตหนึ่งสำหรับ <คือคุณอาจป้องกันไม่ให้เกิดความผิดพลาดทีละมาก ๆ โดยไม่ได้ตั้งใจ


10

@Chris คำแถลงของคุณเกี่ยวกับ. ความยาวที่มีราคาแพงใน. NET นั้นไม่เป็นความจริงและในกรณีของประเภทที่เรียบง่ายตรงกันข้าม

int len = somearray.Length;
for(i = 0; i < len; i++)
{
  somearray[i].something();
}

ช้ากว่าจริง

for(i = 0; i < somearray.Length; i++)
{
  somearray[i].something();
}

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


ใน Java .Length อาจมีค่าใช้จ่ายสูงในบางกรณี stackoverflow.com/questions/6093537/for-loop-optimization b'coz มันสายไปหรือ.lenght .sizeฉันไม่แน่ใจ แต่ไม่มั่นใจ แต่ต้องการให้แน่ใจเท่านั้น
Ravi Parekh

6

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


5

ฉันชอบ:

for (int i = 0; i < 7; i++)

ฉันคิดว่านั่นแปลได้ง่ายกว่าเป็น "การวนซ้ำ 7 ครั้ง"

ฉันไม่แน่ใจเกี่ยวกับผลกระทบด้านประสิทธิภาพ - ฉันสงสัยว่าจะมีการรวบรวมความแตกต่างใด ๆ


4

ใน Java 1.5 คุณสามารถทำได้

for (int i: myArray) {
    ...
}

ดังนั้นสำหรับกรณีอาร์เรย์คุณไม่จำเป็นต้องกังวล


4

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

แก้ไข:ฉันเห็นคนอื่นไม่เห็นด้วย สำหรับฉันโดยส่วนตัวฉันชอบดูตัวเลขดัชนีจริงในโครงสร้างลูป อาจจะเป็นเพราะมันมากขึ้นชวนให้นึกถึงของ Perl ไวยากรณ์ที่ผมรู้ก็คือเทียบเท่า0..6 (0,1,2,3,4,5,6)ถ้าฉันเห็น 7 ฉันต้องตรวจสอบตัวดำเนินการข้างๆเพื่อดูว่าจริงๆแล้วดัชนี 7 ไม่ถึง


ขึ้นอยู่กับว่าคุณคิดว่า "หมายเลขการย้ำครั้งสุดท้าย" สำคัญกว่า "จำนวนการวนซ้ำ" หรือไม่ ด้วย API ที่ใช้ 0 จะแตกต่างกันโดย 1 เสมอ ...
Jon Skeet

4

ฉันจะบอกว่าให้ใช้เวอร์ชัน "<7" เพราะนั่นคือสิ่งที่คนส่วนใหญ่จะอ่านดังนั้นหากมีคนอ่านโค้ดของคุณพวกเขาอาจตีความผิด

ฉันจะไม่กังวลว่า "<" จะเร็วกว่า "<=" หรือไม่เพียงแค่อ่าน

หากคุณต้องการเพิ่มความเร็วให้พิจารณาสิ่งต่อไปนี้:

for (int i = 0; i < this->GetCount(); i++)
{
  // Do something
}

เพื่อเพิ่มประสิทธิภาพคุณสามารถจัดเรียงใหม่เป็น:

const int count = this->GetCount();
for (int i = 0; i < count; ++i)
{
  // Do something
}

สังเกตการลบ GetCount () ออกจากลูป (เนื่องจากจะถูกสอบถามในทุกๆลูป) และการเปลี่ยน "i ++" เป็น "++ i"


ฉันชอบอันที่สองมากกว่าเพราะอ่านง่ายกว่า แต่มันคำนวณค่านี้ -> GetCount () ใหม่ทุกครั้งหรือไม่? ฉันถูกจับได้เมื่อเปลี่ยนสิ่งนี้และการนับยังคงเหมือนเดิมบังคับให้ฉันทำ.. ขณะนี้ -> GetCount ()
osp70

GetCount () จะเรียกว่าการวนซ้ำทุกครั้งในตัวอย่างแรก จะเรียกเพียงครั้งเดียวในตัวอย่างที่สอง หากคุณต้องการเรียก GetCount () ทุกครั้งให้มีการวนซ้ำหากคุณไม่พยายามเก็บไว้ข้างนอก
Mark Ingram

ใช่ฉันได้ลองใช้แล้วและคุณพูดถูกต้องขอโทษด้วย
osp70

การใช้ ++ i มากกว่า i ++ แตกต่างกันอย่างไร
Rene Saarsoo

ความเร็วเล็กน้อยจะเพิ่มขึ้นเมื่อใช้ ints แต่การเพิ่มอาจมากขึ้นหากคุณเพิ่มคลาสของคุณเอง โดยทั่วไป ++ i จะเพิ่มค่าจริงจากนั้นส่งกลับค่าจริง i ++ สร้าง temp var เพิ่มค่า var จริงจากนั้นส่งกลับ temp ไม่จำเป็นต้องสร้าง var กับ ++ i
Mark Ingram

4

ใน C ++ ฉันชอบใช้!=ซึ่งใช้ได้กับคอนเทนเนอร์ STL ทั้งหมด ตัวทำซ้ำคอนเทนเนอร์ STL บางตัวไม่สามารถเทียบเคียงได้


สิ่งนี้ทำให้ฉันกลัวเล็กน้อยเพียงเพราะมีโอกาสภายนอกเล็กน้อยมากที่บางสิ่งบางอย่างอาจวนซ้ำตัวนับมากกว่าค่าที่ฉันตั้งใจไว้ซึ่งจะทำให้เป็นวงวนที่ไม่มีที่สิ้นสุด โอกาสในการตรวจจับจากระยะไกลและง่าย - แต่ < รู้สึกปลอดภัยกว่า
Rob Allen

2
หากมีข้อผิดพลาดเช่นนั้นในโค้ดของคุณอาจจะดีกว่าที่จะผิดพลาดและเบิร์นมากกว่าที่จะดำเนินการต่อไปอย่างเงียบ ๆ :-)

นี่คือคำตอบที่ถูกต้อง: ทำให้มีความต้องการน้อยลงในตัววนซ้ำของคุณและมีแนวโน้มที่จะปรากฏขึ้นหากมีข้อผิดพลาดในโค้ดของคุณ อาร์กิวเมนต์สำหรับ <คือสายตาสั้น บางทีการวนซ้ำที่ไม่สิ้นสุดอาจจะไม่ดีในยุค 70 เมื่อคุณจ่ายเงินสำหรับเวลา CPU '! =' มีโอกาสน้อยที่จะซ่อนข้อบกพร่อง
David Nehme

1
การวนซ้ำเป็นกรณีที่แตกต่างอย่างสิ้นเชิงกับการวนซ้ำด้วยตัวนับ ! = เป็นสิ่งจำเป็นสำหรับผู้ทำซ้ำ
DJClayworth

4

Edsger Dijkstra เขียนบทความเกี่ยวกับเรื่องนี้ในปีพ. ศ. 2525 ซึ่งเขาโต้แย้งว่า <= i <upper:

มีจำนวนน้อยที่สุดตามธรรมชาติ การยกเว้นขอบเขตล่าง - ดังใน b) และ d) - กองกำลังสำหรับลำดับต่อมาโดยเริ่มจากจำนวนธรรมชาติที่เล็กที่สุดขอบเขตล่างตามที่กล่าวถึงในขอบเขตของจำนวนที่ผิดธรรมชาติ มันน่าเกลียดดังนั้นสำหรับขอบเขตล่างเราชอบ≤ใน a) และ c) ตอนนี้พิจารณาลำดับต่อมาที่เริ่มต้นด้วยจำนวนธรรมชาติที่เล็กที่สุด: การรวมขอบเขตบนจะบังคับให้ตัวหลังไม่เป็นธรรมชาติตามเวลาที่ลำดับลดลงเป็นค่าว่าง มันน่าเกลียดดังนั้นสำหรับขอบเขตบนเราชอบ <as in a) และ d) เราสรุปได้ว่าอนุสัญญาก) เป็นที่ต้องการ


3

ขั้นแรกอย่าใช้ 6 หรือ 7

ใช้ดีกว่า:

int numberOfDays = 7;
for (int day = 0; day < numberOfDays ; day++){

}

ในกรณีนี้จะดีกว่าการใช้

for (int day = 0; day <= numberOfDays  - 1; day++){

}

ดียิ่งขึ้น (Java / C #):

for(int day = 0; day < dayArray.Length; i++){

}

และดียิ่งขึ้น (C #)

foreach (int day in days){// day : days in Java

}

การวนซ้ำแบบย้อนกลับนั้นเร็วกว่า แต่เนื่องจากอ่านยากกว่า (ถ้าไม่ใช่คุณโดยโปรแกรมเมอร์คนอื่น) จึงควรหลีกเลี่ยงโดยเฉพาะใน C #, Java ...


2

ฉันเห็นด้วยกับฝูงชนที่บอกว่า 7 มีเหตุผลในกรณีนี้ แต่ฉันจะเพิ่มว่าในกรณีที่ 6 มีความสำคัญบอกว่าคุณต้องการบอกให้ชัดเจนว่าคุณกำลังกระทำกับวัตถุจนถึงดัชนีที่ 6 เท่านั้นจากนั้น <= จะดีกว่าเนื่องจากทำให้ทั้ง 6 มองเห็นได้ง่ายขึ้น


ดังนั้นฉัน <ขนาดเมื่อเทียบกับ i <= LAST_FILLED_ARRAY_SLOT
Chris Cudmore

2

ย้อนกลับไปในวิทยาลัยฉันจำได้ว่ามีบางอย่างเกี่ยวกับการดำเนินการทั้งสองนี้ที่คล้ายกันในเวลาคำนวณบน CPU แน่นอนเรากำลังพูดถึงในระดับการชุมนุม

อย่างไรก็ตามหากคุณกำลังพูดถึงภาษา C # หรือ Java ฉันไม่คิดว่าจะมีการเร่งความเร็วมากกว่าคนอื่น ๆ เพียงไม่กี่นาโนวินาทีที่คุณได้รับมักจะไม่คุ้มค่ากับความสับสนที่คุณแนะนำ

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


2

สิ่งนี้อยู่ในหมวดหมู่"การทำให้รหัสผิดดูผิด"โดยตรง

ในภาษาการจัดทำดัชนีที่อิงศูนย์เช่น Java หรือ C # ผู้คนคุ้นเคยกับการเปลี่ยนแปลงindex < countเงื่อนไข ดังนั้นการใช้ประโยชน์จากอนุสัญญา defacto นี้จะทำให้ข้อผิดพลาดทีละหนึ่งชัดเจนยิ่งขึ้น

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


2

เมื่อมองข้ามอาร์เรย์หรือคอลเล็กชันอื่น ๆ ใน. Net ฉันพบว่า

foreach (string item in myarray)
{
    System.Console.WriteLine(item);
}

เพื่อให้อ่านได้ง่ายกว่าตัวเลขสำหรับการวนซ้ำ แน่นอนว่านี่ถือว่า Int ตัวนับจริงไม่ได้ใช้ในรหัสลูป ไม่ทราบว่ามีการเปลี่ยนแปลงประสิทธิภาพ


นอกจากนี้ยังกำหนดให้คุณไม่ต้องแก้ไขขนาดคอลเลกชันในระหว่างการวนซ้ำ
Jeff B

ดังนั้นสำหรับ (i = 0, i <myarray.count, i ++)
Rob Allen

1

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


1

ฉันมักจะชอบ:

for ( int count = 7 ; count > 0 ; -- count )

เหตุผลของคุณคืออะไร? ฉันสนใจอย่างแท้จริง
Chris Cudmore

นั่นเป็นเรื่องที่ดีอย่างยิ่งสำหรับการวนกลับแบบย้อนกลับ .. ถ้าคุณต้องการสิ่งนั้น
ShoeLace

1
เหตุผลหนึ่งคือที่ระดับ uP เทียบกับ 0 นั้นเร็ว อีกประการหนึ่งคือมันอ่านได้ดีสำหรับฉันและการนับทำให้ฉันบ่งบอกได้ง่ายว่าจะเหลืออีกกี่ครั้ง
kenny

1

การสร้างนิสัยในการใช้ <จะทำให้ทั้งคุณและผู้อ่านสอดคล้องกันเมื่อคุณทำซ้ำผ่านอาร์เรย์ มันจะง่ายกว่าสำหรับทุกคนที่จะมีแบบแผนมาตรฐาน และถ้าคุณใช้ภาษาที่มีอาร์เรย์ที่อิง 0 แสดงว่า <คือแบบแผน

สิ่งนี้มีความสำคัญมากกว่าความแตกต่างด้านประสิทธิภาพระหว่าง <และ <= มุ่งเป้าไปที่ฟังก์ชันและความสามารถในการอ่านก่อนจากนั้นจึงปรับให้เหมาะสม

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


1

อย่าใช้เลขวิเศษ

ทำไมถึงเป็น 7? (หรือ 6 สำหรับเรื่องนั้น)

ใช้สัญลักษณ์ที่ถูกต้องสำหรับหมายเลขที่คุณต้องการใช้ ...

ซึ่งในกรณีนี้ฉันคิดว่าดีกว่าที่จะใช้

for ( int i = 0; i < array.size(); i++ )

1

ตัวดำเนินการ '<' และ '<=' มีต้นทุนประสิทธิภาพเท่ากันทุกประการ

ตัวดำเนินการ '<' เป็นมาตรฐานและง่ายต่อการอ่านในลูปที่อิงศูนย์

การใช้ ++ i แทน i ++ ช่วยเพิ่มประสิทธิภาพใน C ++ แต่ไม่ใช่ใน C # - ฉันไม่รู้เกี่ยวกับ Java


1

ตามที่ผู้คนสังเกตเห็นไม่มีความแตกต่างในสองทางเลือกที่คุณกล่าวถึง เพื่อยืนยันสิ่งนี้ฉันทำการเปรียบเทียบง่ายๆใน JavaScript

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


ทำไมคุณเริ่มต้นด้วย i = 1 ในกรณีที่สอง
Eugene Katz

อืมอาจจะผิดพลาดโง่ ๆ ? ฉันตีมันเร็ว ๆ นี้อาจจะ 15 นาที
David Wees

1

อย่างที่ทุกคนกล่าวว่าเป็นเรื่องปกติที่จะใช้ตัวทำซ้ำที่จัดทำดัชนี 0 แม้กระทั่งกับสิ่งที่อยู่นอกอาร์เรย์ หากทุกอย่างเริ่มต้นที่0และสิ้นสุดที่n-1และขอบเขตล่างเป็นเสมอ<=และขอบเขตบนเสมอ<มีความคิดน้อยกว่าที่คุณต้องทำเมื่อตรวจสอบโค้ด


1

คำถามที่ดี คำตอบของฉัน: ใช้ประเภท A ('<')

  • คุณเห็นได้ชัดเจนว่าคุณมีการทำซ้ำกี่ครั้ง (7)
  • ความแตกต่างระหว่างจุดสิ้นสุดสองจุดคือความกว้างของช่วง
  • ตัวอักษรน้อยลงทำให้อ่านง่ายขึ้น
  • คุณมักจะมีจำนวนองค์ประกอบทั้งหมดi < strlen(s)มากกว่าดัชนีขององค์ประกอบสุดท้ายดังนั้นความสม่ำเสมอจึงมีความสำคัญ

ปัญหาอีกประการหนึ่งคือโครงสร้างทั้งหมดนี้ iปรากฏขึ้น3 ครั้งดังนั้นจึงสามารถพิมพ์ผิดได้ สำหรับวงสร้างกล่าวว่าวิธีการทำแทนสิ่งที่ต้องทำ ฉันขอแนะนำให้ใช้สิ่งนี้:

BOOST_FOREACH(i, IntegerInterval(0,7))

สิ่งนี้ชัดเจนยิ่งขึ้นรวบรวมเพื่อให้คำสั่ง asm ซ้ำกันมากขึ้น ฯลฯ ขอรหัส IntegerInterval ถ้าคุณต้องการ


1

คำตอบมากมาย ... แต่ฉันเชื่อว่าฉันมีบางอย่างที่จะเพิ่ม

การตั้งค่าของฉันคือสำหรับตัวเลขตัวอักษรเพื่อแสดงให้เห็นอย่างชัดเจนว่าสิ่งที่เห็นคุณค่าของ "ฉัน" จะใช้เวลาในวง ดังนั้นในกรณีของการวนซ้ำแม้ว่าอาร์เรย์ที่ใช้ศูนย์:

for (int i = 0; i <= array.Length - 1; ++i)

และถ้าคุณแค่วนลูปไม่วนซ้ำผ่านอาร์เรย์การนับ 1 ถึง 7 นั้นค่อนข้างใช้งานง่าย:

for (int i = 1; i <= 7; ++i)

ความสามารถในการอ่านจะดีกว่าประสิทธิภาพจนกว่าคุณจะกำหนดโปรไฟล์เนื่องจากคุณอาจไม่รู้ว่าคอมไพเลอร์หรือรันไทม์จะทำอะไรกับโค้ดของคุณก่อนหน้านั้น


1

คุณยังสามารถใช้!=แทนได้ ด้วยวิธีนี้คุณจะได้รับลูปที่ไม่มีที่สิ้นสุดหากคุณทำข้อผิดพลาดในการเริ่มต้นทำให้สังเกตเห็นข้อผิดพลาดก่อนหน้านี้และปัญหาใด ๆ ที่ทำให้เกิดการ จำกัด การติดอยู่ในลูป (แทนที่จะมีปัญหาในภายหลังและไม่พบ มัน).


0

ฉันคิดว่าอย่างใดอย่างหนึ่งก็โอเค แต่เมื่อคุณเลือกแล้วให้ยึดมั่นอย่างใดอย่างหนึ่ง หากคุณคุ้นเคยกับการใช้ <= ให้พยายามอย่าใช้ <และในทางกลับกัน

ฉันชอบ <= แต่ในสถานการณ์ที่คุณกำลังทำงานกับดัชนีที่เริ่มต้นที่ศูนย์ฉันอาจจะลองใช้ <. ทั้งหมดเป็นความชอบส่วนบุคคล


0

จากมุมมองเชิงตรรกะอย่างเคร่งครัดคุณต้องคิดว่าสิ่งนั้น< countจะมีประสิทธิภาพมากกว่า<= countเหตุผลที่แน่นอนที่<=จะทดสอบความเท่าเทียมกันด้วย


ฉันไม่คิดอย่างนั้นในแอสเซมเบลอร์มันจะเดือดถึง cmp eax, 7 jl LOOP_START หรือ cmp eax, 6 jle LOOP_START ทั้งคู่ต้องการจำนวนรอบเท่ากัน
Treb

<= สามารถดำเนินการได้! (>)
JohnMcG

! (>) ยังคงเป็นสองคำสั่ง แต่ Treb ถูกต้องว่า JLE และ JL ทั้งคู่ใช้จำนวนรอบนาฬิกาเท่ากันดังนั้น <และ <= ใช้เวลาเท่ากัน
Jacob Krall
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.