2017-10-15 17 views
0

J'essaie d'imprimer la moyenne en Cpp jusqu'à 2 points décimaux de float num. avg est float, sum est float, count est int.Arrondi à la deuxième décimale sauf si le nombre est entier C++

Actuellement, si j'ai 10/1 par exemple, il sort 10.00. Je veux que la sortie soit juste 10. si avg obtient la valeur 3.1467665 par exemple, elle devrait être montrée comme 3.14.

avg = sum/count; 
std::cout << std::fixed << std::setprecision(2) << avg; 

L'arrondi devrait être juste pour la sortie. Pas besoin de changer avg mais si c'est plus facile, sa valeur peut être changée.

Recherche d'une solution utilisant un standard avant C++ 11.

UPD: la sortie est 27,50 quand je veux que ce soit 27,5.

+0

La mise à jour * de manière significative * change la question. Il ne s'agit plus de * "arrondir" *, mais plutôt de "troncature" *. Certes, cela compte toujours comme arrondi (soit vers zéro, soit vers l'infini négatif), mais ce n'est pas ce à quoi les gens s'attendent généralement quand ils voient le terme * «arrondi» * isolément. Correction: Ce n'était pas la mise à jour qui a changé la question. L'exigence de troncature existait dès le début. La réponse proposée ne répond pas à cela. Il produirait '3.15' lorsqu'il est exécuté contre' 3.1467665'. – IInspectable

Répondre

3

Vous pouvez choisir la précision en fonction du module flottant de la valeur avg. Les travaux suivants:

int main() { 
    double sum = 10; 
    double count = 3; 
    double avg = sum/count; 
    double mod; 
    std::cout << std::fixed 
      << std::setprecision((modf(avg, &mod) != 0.0) ? 2 : 0) 
      << avg 
      << std::endl; 
} 

Compte tenu des spécifications ajoutées:

  • Ecrire 2,5 au lieu de 2,50
  • Ecrire 3,14 pour 3,1421783921, plutôt que 3,15

Voici une implémentation possible en utilisant Méthode suggérée par @ IInspectable:

std::stringstream ss; 
    ss << std::fixed << avg; 

    size_t pos = ss.str().find('.'); 
    if (pos + 2 < ss.str().size()) // If there is a '.' and more than 2 digits after it 
    pos += 3; 
    std::string s = ss.str().substr(0, pos); // Leave only two digits 

    s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { return ch != '0'; }).base(), s.end()); // Remove trailing zeros 
    s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { return ch != '.'; }).base(), s.end()); // Remove trailing '.' when needed 
    std::cout << s << std::endl; 

Affichera:

  • 10/4 -> 2.5
  • 10/3 -> 3.33
  • 10/2 -> 5
  • 10/7 -> 1.42
  • 3.9999 -> 3.99
+0

S'il y a un moyen de réécrire ceci en utilisant standart plus ancien (avant c11), ce sera génial. De toute façon, je vais accepter cela comme une réponse. Merci beaucoup. –

+1

Vous pouvez remplacer l'appel 'modf' coûteux par une simple conversion d'entier, par ex. 'auto précision = (int (moy)! = moy)? ...: ...; ', en choisissant un type entier approprié étant donné la plage de valeurs supportée par' avg'. – IInspectable

+0

Eh bien, la sortie est de 27,50 quand je veux que ce soit 27,5. Y a-t-il un moyen de le faire aussi? –