วิธีที่ง่ายและสะอาดในการเปรียบเทียบตัวเลขสามตัว


11

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

a = countAs();
b = countBs();
c = countCs();

if (a > b && a > c)
    status = MOSTLY_A;
else if (b > a && b > c)
    status = MOSTLY_B;
else if (c > a && c > b)
    status = MOSTLY_C;
else
    status = DONT_KNOW;

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


อาจมีการซ้ำซ้อนบางอย่าง แต่พวกเขาไม่สอดคล้องกับคำถามนี้

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

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


3
สำหรับฉันปัญหาเดียวคือการทำซ้ำรหัส สิ่งที่คุณมีอยู่ที่นี่มีความชัดเจนมากในการอ่านทำไมต้องเปลี่ยนสิ่งนั้น เพียงแยกออกเป็นฟังก์ชันที่ใช้ใน a, b, c และส่งคืนสถานะ หากคุณทำให้คุณรู้สึกดีขึ้นให้วาง "อินไลน์" ไว้ ไม่มีมาโครไม่มีความซับซ้อนเพียงแค่ดึงฟังก์ชั่นเก่า ๆ ฉันจะขอบคุณสำหรับรหัสที่ชัดเจนของคุณถ้าฉันต้องการที่จะทำงานกับมันในภายหลัง
J Trana



โปรดทราบว่า #defines ของคุณมีชื่อไม่ดี พิจารณา a = 40, b = 30, c = 30 ผลลัพธ์คือ MOSTLY_A แต่ส่วนใหญ่ไม่ใช่ A แต่ B หรือ C คุณอาจต้องการลอง MORE_A (แม้ว่าจะยังคลุมเครือ - มากกว่า A และ B มากกว่า A มากกว่า C หรือมากกว่า A และ B รวมกันหรือไม่) หรือ A_LARGEST MAX_IS_A, ... ? (ซึ่งยังแนะนำให้ max (a, max (b, c)) เป็นคำตอบสำหรับคำถาม)
โทนี่

คำตอบ:


12

แยกตัวประกอบตรรกะกลับก่อน

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

bool mostly(max,u,v) {
   return max > u && max > v;
}

status_t strictly_max_3(a,b,c)
{
  if mostly(a,b,c) return MOSTLY_A;
  if mostly(b,a,c) return MOSTLY_B;
  if mostly(c,a,b) return MOSTLY_C;
  return DONT_KNOW;
}

นี้สั้นกว่าความพยายามครั้งก่อนของฉัน:

status_t index_of_max_3(a,b,c)
{
  if (a > b) {
    if (a == c)
      return DONT_KNOW;
    if (a > c)
      return MOSTLY_A;
    else
      return MOSTLY_C;
  } else {
    if (a == b)
      return DONT_KNOW;
    if (b > c)
      return MOSTLY_B;
    else
      return MOSTLY_C;
  }
}

ด้านบนเป็น verbose มากกว่าเล็กน้อย แต่ง่ายต่อการอ่าน IMHO และไม่ต้องคำนวณการเปรียบเทียบหลาย ๆ ครั้ง

การยืนยันด้วยสายตา

ในคำตอบของคุณคุณพูดว่า:

ปัญหาของฉันส่วนใหญ่เป็นการยืนยันด้วยภาพว่าการเปรียบเทียบทั้งหมดใช้ตัวแปรเดียวกัน

... ในคำถามของคุณคุณพูดว่า:

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

ฉันอาจไม่เข้าใจสิ่งที่คุณพยายามที่จะบรรลุ: คุณต้องการที่จะคัดลอกรูปแบบทุกที่ที่คุณต้องการหรือไม่ ด้วยฟังก์ชั่อย่างหนึ่งดังกล่าวข้างต้นที่คุณสามารถจับภาพรูปแบบครั้งเดียวและคุณตรวจสอบทุกครั้งที่รถทั้งหมดใช้a, bและcตามความจำเป็น จากนั้นคุณไม่ต้องกังวลอีกต่อไปเมื่อคุณเรียกใช้ฟังก์ชัน แน่นอนว่าในทางปฏิบัติปัญหาของคุณอาจซับซ้อนกว่าที่คุณอธิบายเล็กน้อย: ถ้าเป็นเช่นนั้นโปรดเพิ่มรายละเอียดถ้าเป็นไปได้


1
ฉันไม่เข้าใจความคิดเห็นของคุณเกี่ยวกับDONT_KNOW จะเกิดอะไรขึ้นถ้า c มีขนาดเล็กที่สุดและ a และ b เหมือนกัน อัลกอริทึมจะกลับมาว่า b นั้นใหญ่ที่สุดในขณะที่ a ก็เท่ากับ b
ปีเตอร์ B

@PieterB ผมเป็น wronlgy สมมติว่ามันจะไม่เป็นเรื่องถ้าเรากลับมาอย่างใดอย่างหนึ่งMOSTLY_AหรือMOSTLY_Cในกรณีและa == c a > bสิ่งนี้ได้รับการแก้ไขแล้ว ขอบคุณ
coredump

@DocBrown ได้รับประโยชน์ส่วนใหญ่มาจากพฤติกรรมการออกก่อน
coredump

1
+1 ตอนนี้เป็นการปรับปรุงรหัสต้นฉบับของ OPs
Doc Brown

9

TL: DR; รหัสของคุณถูกต้องแล้วและ "สะอาด"

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

ก่อนอื่นเราทราบว่าเรามี 3 ตัวแปรแต่ละตัวมี 3 สถานะ: <, = หรือ> จำนวนพีชคณิตทั้งหมดคือ 3 ^ 3 = 27 รัฐซึ่งฉันจะกำหนดหมายเลขเฉพาะแทนด้วย P # สำหรับแต่ละรัฐ จำนวน P # นี่คือระบบเลขปัจจัย

ระบุพีชคณิตทั้งหมดที่เรามี:

a ? b | a ? c | b ? c |P#| State
------+-------+-------+--+------------
a < b | a < c | b < c | 0| C
a = b | a < c | b < c | 1| C
a > b | a < c | b < c | 2| C
a < b | a = c | b < c | 3| impossible a<b b<a
a = b | a = c | b < c | 4| impossible a<a
a > b | a = c | b < c | 5| A=C > B
a < b | a > c | b < c | 6| impossible a<c a>c
a = b | a > c | b < c | 7| impossible a<c a>c
a > b | a > c | b < c | 8| A
a < b | a < c | b = c | 9| B=C > A
a = b | a < c | b = c |10| impossible a<a
a > b | a < c | b = c |11| impossible a<c a>c
a < b | a = c | b = c |12| impossible a<a
a = b | a = c | b = c |13| A=B=C
a > b | a = c | b = c |14| impossible a>a
a < b | a > c | b = c |15| impossible a<c a>c
a = b | a > c | b = c |16| impossible a>a
a > b | a > c | b = c |17| A
a < b | a < c | b > c |18| B
a = b | a < c | b > c |19| impossible b<c b>c
a > b | a < c | b > c |20| impossible a<c a>c
a < b | a = c | b > c |21| B
a = b | a = c | b > c |22| impossible a>a
a > b | a = c | b > c |23| impossible c>b b>c
a < b | a > c | b > c |24| B
a = b | a > c | b > c |25| A=B > C
a > b | a > c | b > c |26| A

โดยการตรวจสอบเราเห็นว่าเรามี:

  • 3 สถานะโดยที่ A คือค่าสูงสุด
  • 3 สถานะโดยที่ B คือค่าสูงสุด
  • 3 สถานะโดยที่ C คือค่าสูงสุดและ
  • 4 สถานะโดยที่ A = B หรือ B = C

ลองเขียนโปรแกรม (ดูเชิงอรรถ) เพื่อแจกแจงพีชคณิตทั้งหมดเหล่านี้ด้วยค่าสำหรับ A, B และ C เรียงลำดับอย่างเสถียรโดย P #:

a ?? b | a ?? c | b ?? c |P#| State
1 <  2 | 1 <  3 | 2 <  3 | 0| C
1 == 1 | 1 <  2 | 1 <  2 | 1| C
1 == 1 | 1 <  3 | 1 <  3 | 1| C
2 == 2 | 2 <  3 | 2 <  3 | 1| C
2  > 1 | 2 <  3 | 1 <  3 | 2| C
2  > 1 | 2 == 2 | 1 <  2 | 5| ??
3  > 1 | 3 == 3 | 1 <  3 | 5| ??
3  > 2 | 3 == 3 | 2 <  3 | 5| ??
3  > 1 | 3  > 2 | 1 <  2 | 8| A
1 <  2 | 1 <  2 | 2 == 2 | 9| ??
1 <  3 | 1 <  3 | 3 == 3 | 9| ??
2 <  3 | 2 <  3 | 3 == 3 | 9| ??
1 == 1 | 1 == 1 | 1 == 1 |13| ??
2 == 2 | 2 == 2 | 2 == 2 |13| ??
3 == 3 | 3 == 3 | 3 == 3 |13| ??
2  > 1 | 2  > 1 | 1 == 1 |17| A
3  > 1 | 3  > 1 | 1 == 1 |17| A
3  > 2 | 3  > 2 | 2 == 2 |17| A
1 <  3 | 1 <  2 | 3  > 2 |18| B
1 <  2 | 1 == 1 | 2  > 1 |21| B
1 <  3 | 1 == 1 | 3  > 1 |21| B
2 <  3 | 2 == 2 | 3  > 2 |21| B
2 <  3 | 2  > 1 | 3  > 1 |24| B
2 == 2 | 2  > 1 | 2  > 1 |25| ??
3 == 3 | 3  > 1 | 3  > 1 |25| ??
3 == 3 | 3  > 2 | 3  > 2 |25| ??
3  > 2 | 3  > 1 | 2  > 1 |26| A

ในกรณีที่คุณสงสัยว่าฉันรู้ได้อย่างไรว่า P # state เป็นไปไม่ได้ตอนนี้คุณก็รู้แล้ว :-)

จำนวนขั้นต่ำของการเปรียบเทียบเพื่อพิจารณาคำสั่งซื้อคือ:

Log2 (27) = Log (27) / Log (2) = ~ 4.75 = 5 การเปรียบเทียบ

ie coredump ให้จำนวนการเปรียบเทียบน้อยที่สุด 5 อย่างถูกต้อง ฉันจะจัดรูปแบบรหัสของเขาเป็น:

status_t index_of_max_3(a,b,c)
{
    if (a > b) {
        if (a == c) return DONT_KNOW; // max a or c
        if (a >  c) return MOSTLY_A ;
        else        return MOSTLY_C ;
    } else {
        if (a == b) return DONT_KNOW; // max a or b
        if (b >  c) return MOSTLY_B ;
        else        return MOSTLY_C ;
    }
}

สำหรับปัญหาของคุณเราไม่สนใจเกี่ยวกับการทดสอบความเท่าเทียมกันดังนั้นเราจึงไม่สามารถทดสอบได้ 2 ครั้ง

มันไม่สำคัญว่าโค้ดจะสะอาด / ไม่ดีแค่ไหนหากได้รับคำตอบที่ผิดดังนั้นนี่เป็นสัญญาณที่ดีที่คุณจัดการทุกกรณีอย่างถูกต้อง!

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

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

        if      (a > b && a > c)
            status = MOSTLY_A;
        else if (b > a && b > c)
            status = MOSTLY_B;
        else if (c > a && c > b)
            status = MOSTLY_C;
        else
            status = DONT_KNOW; // a=b or b=c, we don't care

โดยส่วนตัวแล้วฉันจะเขียนด้วยวิธีต่อไปนี้ แต่นี่อาจจะไม่เป็นไปตามมาตรฐานการเข้ารหัสของคุณเกินไป:

        if      (a > b && a > c) status = MOSTLY_A ;
        else if (b > a && b > c) status = MOSTLY_B ;
        else if (c > a && c > b) status = MOSTLY_C ;
        else /*  a==b  || b ==c*/status = DONT_KNOW; // a=b or b=c, we don't care

เชิงอรรถ: นี่คือรหัส C ++ เพื่อสร้างการเรียงสับเปลี่ยน:

#include <stdio.h>

char txt[]  = "< == > ";
enum cmp      { LESS, EQUAL, GREATER };
int  val[3] = { 1, 2, 3 };

enum state    { DONT_KNOW, MOSTLY_A, MOSTLY_B, MOSTLY_C };
char descr[]= "??A B C ";

cmp Compare( int x, int y ) {
    if( x < y ) return LESS;
    if( x > y ) return GREATER;
    /*  x==y */ return EQUAL;
}

int main() {
    int i, j, k;
    int a, b, c;

    printf( "a ?? b | a ?? c | b ?? c |P#| State\n" );
    for( i = 0; i < 3; i++ ) {
        a = val[ i ];
        for( j = 0; j < 3; j++ ) {
            b = val[ j ];
            for( k = 0; k < 3; k++ ) {
                c = val[ k ];

                int cmpAB = Compare( a, b );
                int cmpAC = Compare( a, c );
                int cmpBC = Compare( b, c );
                int n     = (cmpBC * 9) + (cmpAC * 3) + cmpAB; // Reconstruct unique P#

                printf( "%d %c%c %d | %d %c%c %d | %d %c%c %d |%2d| "
                    , a, txt[cmpAB*2+0], txt[cmpAB*2+1], b
                    , a, txt[cmpAC*2+0], txt[cmpAC*2+1], c
                    , b, txt[cmpBC*2+0], txt[cmpBC*2+1], c
                    , n
                );

                int status;
                if      (a > b && a > c) status = MOSTLY_A;
                else if (b > a && b > c) status = MOSTLY_B;
                else if (c > a && c > b) status = MOSTLY_C;
                else /*  a ==b || b== c*/status = DONT_KNOW; // a=b, or b=c

                printf( "%c%c\n", descr[status*2+0], descr[status*2+1] );
            }
        }
    }
    return 0;
}

การแก้ไข: ตามความคิดเห็นย้าย TL: DR ไปที่ด้านบนลบตารางที่ไม่เรียงลำดับออก 27 ฉบับล้างรหัสอธิบายสถานะที่เป็นไปไม่ได้


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

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

2
ขอบคุณสำหรับคำติชมที่สร้างสรรค์ coredump ฉันลบตารางที่ไม่เรียงลำดับตรงกลางออกเนื่องจากตรวจสอบได้ง่าย
Michaelangel007

2
พระเยซู! ใครจะบอกว่าการเปรียบเทียบตัวเลขสามตัวนั้นซับซ้อนพอ ๆ กับวิทยาศาสตร์จรวด?
Mandrill

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

5

@msw บอกให้คุณใช้อาร์เรย์แทน a, b, c และ @Basile บอกให้คุณปรับโครงสร้างตรรกะ "max" ในฟังก์ชั่นอีกครั้ง การรวมความคิดสองข้อนี้เข้าด้วยกัน

val[0] = countAs();    // in the real code, one should probably define 
val[1] = countBs();    // some enum for the indexes 0,1,2 here
val[2] = countCs();

 int result[]={DONT_KNOW, MOSTLY_A, MOSTLY_B, MOSTLY_C};

จากนั้นจัดเตรียมฟังก์ชันซึ่งคำนวณดัชนีสูงสุดของอาเรย์โดยพลการ:

// returns the index of the strict maximum, and -1 when the maximum is not strict
int FindStrictMaxIndex(int *values,int arraysize)
{
    int maxVal=INT_MIN;
    int maxIndex=-1;
    for(int i=0;i<arraysize;++i)
    {
       if(values[i]>maxVal)
       {
         maxVal=values[i];
         maxIndex=i;
       }
       else if (values[i]==maxVal)
       {
         maxIndex=-1;
       }
    }
    return maxIndex;
}

และเรียกว่าชอบ

 return result[FindStrictMaxIndex(val,3)+1];

จำนวน LOC ดูเหมือนจะเพิ่มขึ้นมากกว่าเดิม แต่ตอนนี้คุณมีลอจิกหลักในฟังก์ชั่นที่ใช้ซ้ำได้และถ้าคุณสามารถนำฟังก์ชั่นมาใช้ซ้ำหลายครั้งมันจะเริ่มจ่ายออกไป ยิ่งกว่านั้นFindStrictMaxIndexฟังก์ชั่นนี้ไม่ได้เชื่อมโยงกับ "ข้อกำหนดทางธุรกิจ" ของคุณอีกต่อไป (การแยกข้อกังวล) ดังนั้นความเสี่ยงที่คุณจะต้องแก้ไขในภายหลังนั้นต่ำกว่ารุ่นเดิมของคุณมาก (หลักการแบบเปิดปิด) ตัวอย่างเช่นฟังก์ชันนั้นไม่จำเป็นต้องเปลี่ยนแปลงแม้ว่าจำนวนอาร์กิวเมนต์จะเปลี่ยนแปลงหรือจำเป็นต้องใช้ค่าส่งคืนอื่นนอกเหนือจาก MOSTLY_ABC หรือคุณกำลังประมวลผลตัวแปรอื่นที่ไม่ใช่ a, b, c นอกจากนี้การใช้อาร์เรย์แทนค่าที่แตกต่างกัน 3 ค่าคือ a, b, c อาจทำให้โค้ดของคุณง่ายขึ้นในที่อื่น ๆ เช่นกัน

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


ฉันชอบที่ - ความกล้าFindStrictMaxIndex()อาจไม่สะอาดเกินไป แต่จากมุมมองของผู้โทรมันชัดเจนพอสมควรว่าอะไรคือสิ่งที่พยายามทำให้สำเร็จ
Ken YN

หรือแทนที่จะถือสองอาร์เรย์ให้ถือหนึ่งคู่ของคีย์ - ค่า - คู่: {MOSTLY_A, countAs ()}, ใช้องค์ประกอบแรกที่เรียงลำดับตามค่าและอ่านคีย์
Julia Hayward

@ จูเลียเฮย์เวิร์ด: เหตุผลหลักที่ฉันไม่แนะนำให้ใช้วิธีแก้ปัญหาคือแท็ก "C" ของคำถาม - ใน C คุณจะต้องใช้รหัสสำเร็จรูปเพิ่มเติมเพื่อจัดการกับคู่คีย์ - ค่าและสร้างฟังก์ชันที่พิมพ์ในแง่ของ KVP อาจจะไม่สามารถนำมาใช้ซ้ำได้ในบริบทที่แตกต่างจากintฟังก์ชั่นที่พิมพ์ง่าย แต่ฉันเห็นด้วยกับความคิดเห็นของคุณถ้ามีคนใช้ภาษาอื่นเช่น Python หรือ Perl
Doc Brown

1
@ gnasher729: ขึ้นอยู่กับจำนวน "ซ้ำซ้อน" ในรหัสต้นฉบับเท่าไหร่พวกเขาจะคล้ายกันมากเพียงใดและFindStrictMaxIndexฟังก์ชันสามารถนำมาใช้ซ้ำได้บ่อยเพียงใด สำหรับ reusage หนึ่งหรือสองครั้งนี้จะไม่จ่ายออกแน่นอน แต่นั่นคือสิ่งที่ฉันเขียนไว้แล้วในคำตอบของฉัน สังเกตข้อดีอื่น ๆ ที่ฉันได้กล่าวไว้ข้างต้นเกี่ยวกับการเปลี่ยนแปลงในอนาคต
Doc Brown

1
... และทราบว่าเดิม 8 สายจะถูกแทนที่ด้วยง่ายหนึ่งซับreturn result[FindStrictMaxIndex(val,3)]; ที่จุดในรหัสที่เดิม 8 สายถูกวางไว้ ส่วนอื่น ๆ โดยเฉพาะอย่างยิ่งFindStrictMaxIndexตัวเองจะแยกออกจาก "ตรรกะทางธุรกิจ" อย่างสมบูรณ์ซึ่งย้ายพวกเขาออกจากโฟกัสของการเปลี่ยนแปลงความต้องการทางธุรกิจ
Doc Brown

-1

คุณควรใช้มาโครหรือฟังก์ชั่นที่MAX ให้ตัวเลขสูงสุดสองตัว

จากนั้นคุณเพียงแค่ต้องการ:

 status = MAX(a,MAX(b,c));

คุณอาจกำหนดไว้

 #define MAX(X,Y) (((X)>(Y))?(X):(Y))

แต่ต้องระวัง - ไม่น่าเชื่อเกี่ยวกับผลข้างเคียง - เมื่อใช้มาโคร (เพราะMAX(i++,j--) จะมีพฤติกรรมแปลก ๆ )

ดังนั้นควรกำหนดฟังก์ชั่น

 static inline int max2ints(int x, int y) {
    return (x>y)?x:y;
 }

และใช้มัน (หรืออย่างน้อย#define MAX(X,Y) max2ints((X),(Y)).... )

หากคุณจำเป็นต้องเข้าใจที่มาของ MAX คุณอาจมีมาโครยาวอย่างเช่นมาโคร #define COMPUTE_MAX_WITH_CAUSE(Status,Result,X,Y,Z) แบบยาวdo{... }while(0) บางที

#define COMPUTE_MAX_WITH_CAUSE(Status,Result,X,Y,Z) do { \
  int x= (X), y= (Y), z=(Z); \
  if (x > y && y > z) \
    { Status = MOSTLY_FIRST; Result = x; } \
  else if (y > x && y > z) \
    { Status = MOSTLY_SECOND; Result = y; } \
  else if (z > x && z > y) \
    { Status = MOSTLY_THIRD; Result = z; } \
  /* etc */ \
  else { Status = UNKNOWN; Result = ... } \
} while(0)

จากนั้นคุณสามารถเรียกใช้COMPUTE_MAX_WITH_CAUSE(status,res,a,b,c) ในหลายสถานที่ มันน่าเกลียดนิดหน่อย ฉันกำหนดตัวแปรท้องถิ่นx, y, z เพื่อลดผลข้างเคียงที่ไม่ดี ....


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

1
มาโครควรเป็นเครื่องมือสุดท้าย แน่นอนว่าไม่เหมาะสำหรับปัญหานี้
วินไคลน์

-1

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

a = countAs();
b = countBs();
c = countCs();

if (FIRST_IS_LARGEST(a, b, c))
    status = MOSTLY_A;
else if (SECOND_IS_LARGEST(a, b, c))
    status = MOSTLY_B;
else if (THIRD_IS_LARGEST(a, b, c))
    status = MOSTLY_C;
else
    status = DONT_KNOW; /* NO_SINGLE_LARGEST is a better name? */

ว่าแต่ละคนจะใช้เวลามาโครa, bและcในลำดับเดียวกันเป็นเรื่องง่ายที่จะยืนยันและชื่อแมโครช่วยฉันต้องทำงานสิ่งที่เปรียบเทียบและ ANDs กำลังทำ


1
(1) เหตุใดมาโครเสริมแทนที่จะใช้ฟังก์ชั่น (2) ทำไมคุณต้องมีการยืนยันด้วยภาพที่นี่ มันเป็นปัญหาหลักของคุณจริง ๆ หรือจำเป็นต้องมีการยืนยันด้วยภาพอันเป็นผลมาจากการทำสำเนารหัสหรือไม่? ตัวเลือกที่ดีที่สุดของคุณคือการแยกขนาดรหัสของคุณให้เป็นฟังก์ชั่นเดียวที่เรียบง่ายที่คุณตรวจสอบทุกครั้ง
coredump
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.