2017-08-15 64 views
1

具有用於設計的一美元的價值輸入轉換成其可能的構成部分中的程序浮子/ INT計算麻煩。例如,如果您輸入$ 1234.56,程序會輸出 「1個$ 1000個法案,2個$ 100大鈔,1個$ 20法案,1頁$ 10的法案,4 $ 4美元的鈔票,2個季度,1鎳,和1分。」印刷值int對於一個簡單的計算(值不相加)

最大的問題出現與計算便士。如果用戶輸入$ .03,則輸出會有所不同(有時,我得到3美分;其他時間,我得到2美分)。我想我已經解決了這個問題,現在,但我想知道爲什麼我解決它,更重要的是我想解決根本的問題:沿計算流的地方,編譯器會出現在「刮掉」值(例如.01變成0.009999)。是因爲我正在對同一個變量進行遞歸計算,即「數量」?有沒有更乾淨的方式來做我想在這裏做的事情? (我有限切換/選擇是否陳述,沒有用的功能,並且不使用陣列。)

鏈接到全碼here

#include <stdio.h> 

int main(){ 

float amount, bill_quarter_f, bill_dime_f, bill_nickel_f, bill_penny_f; 
int bill_quarter, bill_dime, bill_nickel, bill_penny; 

printf("Ex 5.15: Translating Decimal Dollar into Coins\n"); 
printf("==============================================\n\n"); 

printf("Enter your amount (e.g .98): $ "); 
scanf("%f", &amount); 

/************************************/ 
/* Calculation for greater than MAX */ 
/************************************/ 

if (amount >= 1) 
    printf("\nYou have too much money!\n\n"); 

/************************************/ 
/*  Calculation for Coins  */ 
/************************************/ 

else if(amount < 1 && amount > 0){ 
    bill_quarter = amount/.25; 
    bill_quarter_f = amount/.25; 
    amount = ((bill_quarter_f - bill_quarter) * .25); 


    (bill_quarter >= 1 && bill_quarter < 4) ? (printf("You have %d quarters\n", bill_quarter)) : (printf("")); 

    bill_dime = amount/.10; 
    bill_dime_f = amount/.10; 
    amount = (bill_dime_f - bill_dime) * .10; 


    (bill_dime >= 1 && bill_dime <= 2) ? (printf("You have %d dimes\n", bill_dime)) : (printf("")); 

    bill_nickel = amount/.05; 
    bill_nickel_f = amount/.05; 
    amount = (bill_nickel_f - bill_nickel) * .05; 


    (bill_nickel >= 1 && bill_nickel < 2) ? (printf("You have %d nickel\n", bill_nickel)) : (printf("")); 

    bill_penny = amount/.01; 
    bill_penny_f = amount/.01; 
    amount = (bill_penny_f - bill_penny) * .01; 

    (bill_penny_f > 0 && bill_penny_f < 5) ? (printf("You have %.0f pennies\n", bill_penny_f)) : (printf("")); 
} 

else if (amount == 0) 
    printf("You have no money!\n"); 
else 
    printf("You are in debt!\n"); 

return 0; 
} 
+0

使用定點運算的貨幣種類;浮點是完全不合適的(二進制浮點尤其如此)。 –

+0

@TobySpeight貨幣類型的定點算法也有其弱點。 「浮點數完全不合適」 - >十進制浮點數很大 - 除了缺乏支持。無論採取何種路線,它都是一種折衷。 – chux

+0

@chux,我從來沒有嘗試十進制浮點數的錢;我寧願將這些指數數字用於實際值,而不是用於縮放(以及在意外時間改變(絕對)精度)。但是如果你有經驗,我很想聽聽它是如何工作的,也許是在某個地方的答案? –

回答

1

對財務代碼使用二進制浮點有各種缺陷。 OP的代碼展示了其中的一些。如果沒有其他方式來表示金錢(每個方式都有自己的優缺點),那麼這個答案就會提出一些方法來改善double的用法,因爲它適用於OP的代碼。的錢

  1. 不精確表示

召回一個binary64double通常可以準確代表約2 不同的號碼。 0.10不是其中之一。所以下面的商通常會導致一個非整數。

float amount; 
... 
amount/.10; 

分配商到int導致截短的值。有quotient是1.9999 ...,bill_dime將採取的1

int bill_dime; 
... 
bill_dime = amount/.10; 
  • 超過輸入無控制不是0.01的整數倍。
  • 做什麼用的像"0.125"用戶輸入 - >amount = 0.125

    0.125可以精確地表示爲double,所以輸入時不存在舍入問題。然而,代碼並沒有解決如何將這個值舍入或者如何處理0.01的分數。

  • 在輸入查詢舍入值沒有控制。
  • 如何處理用戶輸入如"0.10" - >該值無法準確表示?所以附近的amount = 0.10f結果。

    value呈現出float0.01f接近 0。01並可能與double0.01有所不同。這種差異可能會導致amount/.10;的意外結果。混合doublefloat促成了這個問題。


    對於採用FP金融代碼,請不要使用float - 太多太多的問題。

    對於OP的學習者使用FP和財務代碼,建議將FP輸入轉換爲整數以進行更改計算。由於下面的轉換爲long當然不會溢出,所以可以將OF的關注放在一邊。

    printf("Enter your amount (e.g .98): $ "); 
    double amount; 
    if (scanf("%lf", &amount) != 1) Handle_NonNumericInput(); 
    
    if (amount >= 1.0 || amount < 0.0) 
        printf("\nYou have too much/too little money!\n\n"); 
    

    現在移動到整數

    else { 
        // round ... to the nearest integer value, rounding halfway cases away from zero, 
        long cents = lround(amount * 100.0); 
        // 0 <= cents <= 100 
        // Need to decide how to handle cents == 0 or cents == 100 here. 
    
        bill_quarter = cents/25; 
        cents %= 25; 
    
        if (bill_quarter) { 
        printf("You have %d quarters\n", bill_quarter); 
        } 
    
        bill_dime = cents/10; 
        cents %= cents % 10; 
    
        if (bill_dime) { 
        printf("You have %d dimes\n", bill_dime); 
        } 
    

    // "You have %d nickel" 
    "You have %d nickels"