2017-10-15 4 views
0

Ich versuche, den Durchschnitt in Cpp bis zu 2 Dezimalpunkte der float Nummer zu drucken. avg ist float, sum ist float, count ist int.Runden auf die zweite Dezimalstelle, es sei denn, die Zahl ist ganz C++

Derzeit, wenn ich 10/1 zum Beispiel habe, gibt es 10.00 aus. Ich möchte, dass der Ausgang nur 10 ist. Wenn avg den Wert 3.1467665 erhält, sollte es beispielsweise als 3.14 angezeigt werden.

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

Die Rundung sollte nur für die Ausgabe sein. Keine Notwendigkeit zu ändern avg, aber wenn es einfacher ist, kann der Wert geändert werden.

Auf der Suche nach einer Lösung mit einem Standard vor C++ 11.

UPD: der Ausgang ist 27.50, wenn ich möchte, dass es 27.5 ist.

+0

Das Update * deutlich * ändert die Frage. Es fragt nicht mehr nach * "Runden" *, sondern nach * "Abschneiden" *. Zugegeben, das gilt immer noch als Rundung (entweder in Richtung Null oder Neg. Unendlichkeit), aber es ist nicht das, was die Leute allgemein erwarten, wenn sie isoliert den Begriff * "runden" sehen. Korrektur: Es war nicht das Update, das die Frage änderte. Die Kürzungsanforderung war von Anfang an da. Die vorgeschlagene Antwort spricht das nicht an. Es würde '3.15' produzieren, wenn es gegen' 3.1467665' läuft. – IInspectable

Antwort

3

Sie können die Genauigkeit gemäß dem Floating Modul des Werts avg wählen. Die folgenden Werke:

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; 
} 

die zusätzlichen Spezifikationen unter Berücksichtigung

  • schreiben 2,5 statt 2,50
  • 3.14 Schreiben für 3,1421783921 statt 3,15

Hier ist eine mögliche Implementierung mit @Inspectable's vorgeschlagene Methode:

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; 

erhalten Sie folgende Ausgabe:

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

Wenn es eine Möglichkeit gibt, dies mit älteren Standart (vor c11) umzuschreiben, wird es großartig. Wie auch immer, ich werde das als Antwort akzeptieren. Vielen Dank. –

+1

Sie könnten den kostspieligen 'modf'-Aufruf durch eine einfache ganzzahlige Umwandlung ersetzen, z. 'automatische Präzision = (int (avg)! = avg)? ...: ...; ', wobei ein geeigneter ganzzahliger Typ unter Berücksichtigung des unterstützten Wertebereichs für' avg' ausgewählt wird. – IInspectable

+0

Nun, die Ausgabe ist 27,50, wenn ich will, dass es 27,5 ist. Gibt es einen Weg, dies auch zu tun? –

Verwandte Themen