2013-06-22 93 views
1
#include <cs50.h> 
#include <stdio.h> 

int main(void) { 

    printf("Enter your change: "); 
    int pennies = 0, nickels = 0, dimes = 0, quarters = 0; 
    float change = GetFloat(); 

    while (change > 0) { 
     if (change >= 0.25) { 
      quarters++; 
      change -= 0.25; 
     } 
     else if (change >= 0.10) { 
      dimes++; 
      change -= 0.10; 
     } 
     else if (change >= 0.05) { 
      nickels++; 
      change -= 0.05; 
     } 
     else if (change >=0.01) { 
      pennies++; 
      change -= 0.01; 
     } 
     // force break 
     else { 
     printf("%1.2f - Num. of change left\n", change); 
     break; 
     } 
    } 
    printf("Quarters: %d\n", quarters); 
    printf("Dimes: %d\n", dimes); 
    printf("Nickels: %d\n", nickels); 
    printf("Pennies: %d\n", pennies); 
    return 0; 
} 

你好,我目前是C的新手,我正在哈佛大學的CS50班上線。 「更改」變量似乎降低到0.00而不停止while循環。這迫使我在最後輸入「break」。我的代碼有什麼問題?C while-loop not stopping

這是來自問題集1的方式。

+1

認真地說,'浮動'來計算*積分*分數?!?! –

+1

http://floating-point-gui.de/ –

+1

感謝您提供指向您參考的信息的鏈接,例如http://d2o9nyf4hwsci4.cloudfront.net/2012/fall/psets/1/pset1.pdf。注意腳註9本文檔中:「對於\t 例如,\t 0.01 \t 不能\t 是\t 代表\t 正是\t 作爲\t 一個\t 浮動」 –

回答

6

浮點數如何在計算機內存中表示出現問題。簡而言之:並非所有數字都可以精確存儲。請閱讀此頁瞭解詳情:http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

您可以使用該服務來檢查花車的表示在計算機:http://www.binaryconvert.com/result_float.html

關於你的情況,讓我們假設你已經進入0.4。這意味着它應該分爲0.25 + 0.1 + 0.05。而change應該是零,但:

0.40 == 0.4000000059604644775390625000, 
minus 
0.25 == 0.2500000000000000000000000000 (exact), 
minus 
0.10 == 0.1000000014901161193847656250, 
minus 
0.05 == 0.0500000007450580596923828125 
is 
0.00 == 0.0000000037252902984619140625 

正如你所看到的,最後的結果是略高於零,是什麼阻止你的循環結束從。

一般來說,如果您需要數錢,您應該使用int來代替「仙」。或自定義類型。或長算術。或者是什麼,但不是浮點,因爲大多數國家的資金在一個點之後只需要兩個頭寸,因此這一點不需要是浮動

+2

+1顯示實際的數字。 –

0

您應該使用getFloat()的等效整數,或者使用整數變量來進行比較。由於浮點問題,代碼出錯了。

#include<math.h> // for round 
... 
... 
    int change = int)100 * round(getFloat()); 
+0

他會想要乘以100前四捨五入和轉換爲「int」... –

+0

是的 - 謝謝本 – suspectus

1

正如其他人所說,這是一個浮點問題。這是你的問題:

else if (change >=0.01) { 
      pennies++; 
      change -= 0.01; 
     } 

什麼是可能發生的是,change結束了超過0.01非常略高,所以當你減去這0.01,它最終被比零稍大,但小於0.01,和你有沒有if條款來處理這種可能性,所以它永遠持續下去。您的printf()顯示爲零,因爲您將其舍入到小數點後兩位,所以它看起來像0.00,即使它可能是0.00001或某物。

1

這是不明智的使用花車爲此,如上所述這裏好幾次......

邏輯,你可以做你想什麼,我懷疑它與做對比和用C促銷規則...但我猜這將解決你的問題:

while (change > 0.0f) 

這樣你比較喜歡的類型......

真的,你應該改變使用的int,long或長長...並代表美分而非th一美元。

+0

這我猜只會工作,如果事實上你有足夠的得到小於零。 –

1

未經測試,但以下是我如何寫它。它使用int而不是float來避免舍入問題,對每個硬幣都有一個表驅動計算,並且進行除法而不是重複減法。

int change = GetFloat() * 100 + 0.5; 
struct {const char *name; int value;} coins[] = { 
    {"Quarters", 25}, 
    {"Dimes", 10}, 
    {"Nickels", 5}, 
    {"Pennies", 1}, 
}; 
for (int i = 0; i < 4; i++) { 
    int coin = change/coins[i].value; 
    change %= coins[i].value; 
    printf("%s: %d\n", coins[i].name, coin); 
}