2012-10-29 1 views
1

Je n'arrive pas à comprendre pourquoi cela fonctionne pour 90% des entrées, mais pas pour les autres. Il est destiné à vous dire combien de pièces vous retiendrez en changement. La plupart des montants de test fonctionnent bien, mais si vous entrez 4,20 (ou 4,20 $), il renvoie 23 pièces ... il devrait être de 18 pièces (16 quarts et 2 nickels). Où est le bug? Voici mon code:Petit bug dans mon code C court. Pourquoi?

#include <stdio.h> 
#include <cs50.h> 

int main(void){ 

    float change = 0.00; 

    printf("How much change is owed? "); 
    change = GetFloat(); 

    float quarters = change/.25; 
    change-= (int)quarters*.25; 

    float dimes = change/.10; 
    change-= (int)dimes*.10; 

    float nickels = change/.05; 
    change-= (int)nickels*.05; 

    float pennies = (change+.005)/.01; 
    change-=(int)pennies*.01; 

    int total = (int)quarters+(int)dimes+(int)nickels+(int)pennies; 

    printf("%d\n", total); 

    return 0; 
    } 
+7

Vous ne devez jamais utiliser les nombres à virgule flottante pour représenter l'argent en premier lieu. –

+0

Puisque tout est un multiple de 1 cent, pourquoi ne pas tout stocker comme un nombre entier de centimes? Vous éviterez ainsi tous les problèmes liés aux virgules flottantes. –

+0

Ceci est un devoir qui est censé enseigner les fonctions de flotteur, c'est la seule raison pour laquelle il est écrit comme il est. C'est juste bizarre que la plupart des entrées fonctionnent bien, seulement certains chiffres ne le font pas. Je ne peux pas le réécrire en utilisant différentes classes ou quoi que ce soit, parce que c'est la façon dont le professeur veut le voir. –

Répondre

2

Jeter les calculs en virgule flottante. Tout est basé sur des centièmes au mieux, il suffit d'utiliser la division entière/modulo. Jamais ne compte sur une précision parfaite dans les nombres à virgule flottante.

#include <stdio.h> 
#include <cs50.h> 

int main(void){ 

    float fchange = 0.00; 
    int change = 0; 

    printf("How much change is owed? "); 
    fchange = GetFloat(); 

    change = (int)roundf(fchange*100.0); 

    int quarters = change/25; 
    change = change % 25; 

    int dimes = change/10; 
    change = change % 10; 

    int nickels = change/5; 
    change = change % 5; 

    printf("%d quarters, %d dimes, %d nickels, %d pennies\n", quarters, dimes, nickels, change); 

    return 0; 
} 
+0

'change = (int) (fchange * 100.0);' <- vous avez besoin d'arrondir là, la troncature conduit à de mauvais résultats pour certaines entrées (par exemple 4.20). –

+0

@DanielFischer Merci Daniel. Je répondais totalement à une question différente quand je l'ai posté sans la terminer (doigts phat). – WhozCraig

+0

Multitâche? J'aimerais pouvoir faire cela. –

6

La valeur la plus proche float à 4.20 est légèrement inférieur à celui (4,19999980926513671875, pour les 32 bits IEEE754 float habituels s). Donc, après avoir soustrait les 4 $ des 16 trimestres, il vous reste un montant légèrement inférieur à 0,2. Si vous divisez par 0,1, la valeur est légèrement inférieure à 2, donc votre valeur nickels est égale à 1. La même chose arrive après que vous soustrayez votre nickel, la valeur est légèrement inférieure à 0,1, divisant par 0,05 donne un quotient légèrement inférieur à 2.

Vous devez utiliser des entiers uniquement pour un tel calcul, en calculant en cents.

+0

En Objective-C, la classe 'NSDecimalNumber' est aussi une option, mais ce serait beaucoup plus compliqué. – Tommy

+0

+1 pour la valeur IEEE exacte. Avez-vous calculé cela à la main ou à partir d'un site Web? –

+0

Je laisse mon interpréteur Haskell calculer que 'fromRational' convertit un nombre rationnel en le nombre à virgule flottante le plus proche. –

1

Les autres réponses l'ont principalement couvert: vous devriez travailler avec un point fixe ici, pas de virgule flottante. Veillez à bien arrondir lorsque vous passez de l'entrée à virgule flottante à la représentation à virgule fixe. Voici une version courte, je piraté, ce qui devrait fonctionner pour toutes les entrées positives:

#include <stdlib.h> 
#include <stdio.h> 
int main(int argc, char ** argv) 
{ 
    float change = atof(argv[1]); 
    int work = (int)(100*change+0.5); 
    int quarters, dimes, nickels, pennies; 
    quarters = work/25; work %= 25; 
    dimes = work/10; work %= 10; 
    nickels = work/5; work %= 5; 
    pennies = work; 
    printf("%.2f dollars = %d quarters, %d dimes, %d nickels and %d pennies: %d coins total\n", 
    change, quarters, dimes, nickels, pennies, quarters+dimes+nickels+pennies); 
    return 0; 
} 

Par exemple:

./change 4.20 
4.20 dollars = 16 quarters, 2 dimes, 0 nickels and 0 pennies: 18 coins total