簡體   English   中英

這些被認為是魔術數字嗎?

[英]Would These Be Considered Magic Numbers?

我剛剛完成了為編程課程編寫程序,我想避免使用魔術數字,所以這是我的問題:

在下面的函數中,我的數組索引器是否會被視為幻數?

碼:

string CalcGrade(int s1, int s2, int s3, double median)
{
const int SIZE = 23;
const int LETTER_GRADE_BARRIERS[SIZE] = { 400, 381, 380, 361, 360, 341, 340, 321, 320, 301, 300, 281, 280, 261, 260, 241, 240, 221, 220, 201, 200, 181, 180 }; 
double finalGrade;
string letterGrade;

finalGrade = s1 + s2 + s3 + median;

if (finalGrade >= LETTER_GRADE_BARRIERS[1] && finalGrade <= LETTER_GRADE_BARRIERS[0])
{
    letterGrade = "A";
}
else if (finalGrade >= LETTER_GRADE_BARRIERS[3] && finalGrade <= LETTER_GRADE_BARRIERS[2])
{
    letterGrade = "A-";
}
else if (finalGrade >= LETTER_GRADE_BARRIERS[5] && finalGrade <= LETTER_GRADE_BARRIERS[4])
{
    letterGrade = "B+";
}
else if (finalGrade >= LETTER_GRADE_BARRIERS[7] && finalGrade <= LETTER_GRADE_BARRIERS[6])
{
    letterGrade = "B";
}
else if (finalGrade >= LETTER_GRADE_BARRIERS[9] && finalGrade <= LETTER_GRADE_BARRIERS[8])
{
    letterGrade = "B-";
}
else if (finalGrade >= LETTER_GRADE_BARRIERS[11] && finalGrade <= LETTER_GRADE_BARRIERS[10])
{
    letterGrade = "C+";
}
else if (finalGrade >= LETTER_GRADE_BARRIERS[13] && finalGrade <= LETTER_GRADE_BARRIERS[12])
{
    letterGrade = "C";
}
else if (finalGrade >= LETTER_GRADE_BARRIERS[15] && finalGrade <= LETTER_GRADE_BARRIERS[14])
{
    letterGrade = "C-";
}
else if (finalGrade >= LETTER_GRADE_BARRIERS[17] && finalGrade <= LETTER_GRADE_BARRIERS[16])
{
    letterGrade = "D+";
}
else if (finalGrade >= LETTER_GRADE_BARRIERS[19] && finalGrade <= LETTER_GRADE_BARRIERS[18])
{
    letterGrade = "D";
}
else if (finalGrade >= LETTER_GRADE_BARRIERS[21] && finalGrade <= LETTER_GRADE_BARRIERS[20])
{
    letterGrade = "D-";
}
else if (finalGrade <= LETTER_GRADE_BARRIERS[22])
{
    letterGrade = "Fail";
}

return letterGrade;
}

謝謝!

是的,除了-1,0或1之外的任何數字都可能是一個神奇的數字。

除非你是一個真正的大師,否則你可能也被允許自由使用兩個權力:-)

順便說一句,你可能可以重構那些代碼,使其更容易理解,例如:

string CalcGrade (int s1, int s2, int s3, double median) {
    // Grade lookup arrays. If grade is >= limit[n], string is grades[n].
    // Anything below D- is a fail.
    static const int Limits[] = {400, 380, 360, 340,320, 300, 280,260, 240, 220,200,180 }; 
    static const int Grades[] = {"A+","A","A-","B+","B","B-","C+","C","C-","D+","D","D-"};

    double finalGrade = s1 + s2 + s3 + median;

    // Check each element of the array and, if the final grade is greater
    //   than or equal to, return the grade string.
    for (int i = 0; i < sizeof(Limits) / sizeof(*Limits); i++)
        if (finalGrade >= Limits[i])
            return Grades[i];

    // Otherwise, failed.
    return "Fail";
}

這將刪除遍布代碼的魔術數字到一個區域,在這個區域中,它們的工作方式很明顯(假設您很好地對齊它們)。

它也與原來的解決方案中刪除的問題,以什么我們與別人,達到380.5的得分做-這不是真正的公平失敗:-)或者那些的BOD一個檔次分配給""對上述400(因為沒有按似乎是回歸"A+"一種方式。

在你正在做事的時尚中 ,我會說它們不是神奇的數字。 你會把它們重命名為什么? 我想不出任何有用的答案( static const int One = 1;沒用。)

400, 381,等等線路起初對我來說更加困惑。 我會在其上面加上一些類似於// GPA times 100來澄清。

事實上,雖然你的問題(數組索引)不是太神奇,但400...行應該用static const int A = 400; static const int AMinus = 381;替換static const int A = 400; static const int AMinus = 381; static const int A = 400; static const int AMinus = 381; 然后...BARRIERS[] = {A, AMinus,}等等。 這些絕對是有意義的常數

有替代(更清潔)的方法需要數字,絕對應該變成命名常量。 (以上建議的相同)

是。 您需要重新編譯才能更改數字; 這就是問題所在。

任何類似的配置都應該是可配置的,不需要重新編譯。 當然,您的配置中可能仍有數字,但在您的情況下,它似乎都是配置表的合法數據。

怎么樣怎么這樣做了一點幽默的?

string CalcGrade (int s1, int s2, int s3, double median) {
    int grade = median + s1 + s2 + s3;
    grade = (grade>400)?400:((grade<180)?179:grade);
    return
        "Fail\0D-\0\0\0D\0\0\0\0D+\0\0\0C-\0\0\0C\0\0\0\0"C+\0\0\0"
        "B-\0\0\0B\0\0\0\0B+\0\0\0A-\0\0\0A\0\0\0\0A+"[((grade-160)/20)*5];
}

LETTER_GRADE_BARRIERS的定義與它們實際代表的內容不LETTER_GRADE_BARRIERS ,所以是的。 如果它是一個int和char *(標記)的結構數組,那么沒有。

是的,但它們使用常量正確表示,所以沒有問題。

但是,我會考慮將字母等級分配給另一個數組並將它們與障礙對齊。

我肯定會使用一個循環而不是分別寫出12個案例中的每一個。

它可以看起來更簡單,例如使用std::lower_bound來查找哪個括號分數和字母數組,例如letter_grade[]= { "A", ... }; 將括號轉換為字母等級

是的,他們絕對是神奇的數字。 你的方式也沒有幫助。 所有這些數字間隔20步(每個數字之前有額外的+1緩沖區),但這在代碼中並不明顯。 一個更好的實現將是這樣的:

string CalcGrade(int s1, int s2, int s3, double median) {
  const int MAXIMUM_GRADE = 400;
  const int MINIMUM_GRADE = 180;
  const int GRADE_STEP = 20;
  const char* GRADES[] = { "A", "A-", "B+", "B", "B-", "C+", "C", "C-", "D+", "D", "D-" };

  double finalGrade = s1 + s2 + s3 + median;

  if (finalGrade >= MAXIMUM_GRADE) {
    return "A+";
  } else if (finalGrade <= MINIMUM_GRADE) {
    return "Fail";
  } else {
    return GRADES[(size_t)((MAXIMUM_GRADE - finalGrade) / GRADE_STEP)];
  }
}

是。 數組中的索引沒有任何語義含義。 這讓他們變得“神奇”。

paxdiablo的反應是一種非常好的方法,盡管我很想將限制和等級名稱組合成一個類/結構。

即使保持代碼結構,請考慮以下兩個片段:

// original
else if (finalGrade >= LETTER_GRADE_BARRIERS[13] && finalGrade <= LETTER_GRADE_BARRIERS[12]) 
{ 
    letterGrade = "C"; 
} 

// compared to
else if (finalGrade >= MIN_C_GRADE && finalGrade < MIN_C_PLUS_GRADE)
{
    letterGrade = "C";
}

第二個樣本為代碼附加了更多的語義含義,而不是依賴於'13'和'14'代表什么。

將它們存儲在一個數組中幾乎沒有什么收獲,因為你實際上沒有迭代數組。

對魔術數字的一個很好的檢查是向某人描述問題的解決方案。 如果這些數字沒有出現在你的口頭描述中,那么它們幾乎肯定是神奇的。

如果你在談論構成LETTER_GRADE_BARRIERS數組內容的LETTER_GRADE_BARRIERS ,我可能LETTER_GRADE_BARRIERS這些數字視為數據 ,而不一定是值得使用唯一名稱的數字。

我猜想理想情況下它們會來自數據文件而不是嵌入到程序中,但您的任務/要求可能會另有規定。

但是,用於索引數組的數字可能值得命名。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM