2017-09-25 1 views
1

Cela fait partie d'un programme plus vaste mais la seule partie qui me pose problème est la génération de la table des valeurs calculées commençant et se terminant à valeur initiale et finale. Pour une raison quelconque, lorsque la valeur d'incrément donnée est 0.2, cela fonctionne parfaitement bien, mais lorsque la valeur donnée est 0.05, elle n'affiche pas la valeur finale.Essayer de créer une table de valeurs calculées et initiales à la valeur finale incrémentée d'un nombre donné

ici est le code que j'ai pour cette section:

for (volume = initialVol; volume <= finalVol; volume += volumeIncrement) { 

    pressure = pressure_cal(gasNumber, temperature, volume, gasQuantity); 

    printf("%.3lf\t\t\t %.4lf\n", volume, pressure); 
} 

De plus, si je change la condition for à volume <= finalVol + volumeIncrement, cela fonctionnera pour 0.05, mais pas 0.2.

edit: J'ai pensé que j'ajouterais aussi que si je remplace la fonction userdef avec, disons, pression = 1; les valeurs affichées pour le volume ne sont pas affectées.

+0

et cette fonction ?: *** pressure_cal (gasNumber, température, volume, gasQuantity) *** –

+0

Il est fonction de calculer une valeur pour la pression avec la valeur donnée pour le volume. Il est supposé incrémenter par volumeIncrément (0.2 ou 0.05) et calculer toutes les valeurs de pression possibles du volume initial au volume final. –

+0

peut-être que cette fonction est celle qui ne fonctionne pas .... –

Répondre

1

Le problème provient des erreurs d'arrondi dans les calculs à virgule flottante concernant les factions qui ne peuvent pas être représentées avec précision au format double ou float. Vos incréments de 0.2 ou 0.05 sont des multiples entiers de puissances négatives de 2, de sorte que la représentation au format binaire IEEE est arrondie:

  • Si volumeIncrement est arrondi à une valeur inférieure, la réussira épreuve finale car volume sera un un peu plus petit que finalVol. C'est ce qui arrive pour 0.2; Inversement, si volumeIncrement est arrondi à une valeur plus grande, le test final échouera car volume dépassera finalVol. C'est ce qui arrive pour 0.05.

Il y a plusieurs façons d'éviter ce problème:

  • Vous pouvez ajouter une petite valeur à volume pour assurer la comparaison finale réussit: volume <= finalVol + volumeIncrement/2 serait un moyen simple pour y parvenir.
  • Vous pouvez utiliser l'arithmétique entière et convertir uniquement en virgule flottante pour les calculs, pas pour l'énumération. Vous utiliseriez par exemple des nombres entiers de millilitres au lieu de nombres fractionnaires de litres et utilisez des incréments de 20 ou 5.
  • Vous pouvez spécifier le nombre de pas au lieu de l'incrément.

Voici le code modifié pour la dernière approche:

int steps = 100; 
for (int step = 0; step <= steps; step++) { 
    double volume = initialVol + (finalVol - initialVol) * step/steps; 
    double pressure = pressure_cal(gasNumber, temperature, volume, gasQuantity); 
    printf("%.3f\t\t\t %.4f\n", volume, pressure); 
}