cout - Nachkommastellen angeben?



  • Hallo,
    ich hab hier glaub ich ne Anfängerfrage bei der ich aber leider gerade nicht weiterkomme.

    Ich möchte, zu Übungszwecken, einen Rundungsalgorithmus selber schreiben. Ist auch soweit kein Problem.
    Nur wie kann ich die Anzahl der Nachkommastellen mit cout angeben? Am besten noch dynamisch mit ner Variablen? Das Check ich grad nicht. 😞

    Danke für die Hilfe
    geneticZ





  • ja danke, das kannte ich schon habs nicht verwendet weils eben rundet.



  • geneticZ schrieb:

    ja danke, das kannte ich schon habs nicht verwendet weils eben rundet.

    klar rundet es, so lang du dort nicht die maximale länge für den jeweiligen typen angibst(float/double/long double)
    wenn du ne 1.999999999999999999999999 ausgeben willst, aber nur 5 dezimalstellen anzeigen lassen willst, soll er dann 1.99999 ausgeben? ich glaube nicht...

    bb


  • Mod

    Also wenn du was ungerundetes willst, kann man so einen Ansatz machen:

    #include <iostream>
    #include<sstream>
    
    using namespace std;
    
    template<typename T> class precise;
    
    template<typename T> ostream& operator<<(ostream& stream,precise<T> obj){
      stringstream s;
      s<<obj.data;
      stream<<s.str().substr(0,obj.num)<<endl;
      return stream;
    };
    
    template<typename T> class precise{
    private:
      int num;
      T data;
    public: 
      precise(int i, T t): num(i), data(t) {};
      friend ostream& operator<< <>(ostream& stream, precise obj);
    };
    
    int main(){
      cout<<precise<double>(5, 1.2345678);
    }
    

    Geht für alle Typen die einen stringstream Operator << haben. Man kann noch eine Menge verbessern, da ich es gerade schnell hingeschrieben habe ohne auf Feinheiten zu achten: Const correctness nicht beachtet, keine Referenzen für data verwendet, gibt wirklich exakt die Anzahl Zeichen aus, egal ob es sich um Vor-/Nachkommastellen oder gar das Komma selbst handelt. Die Idee sollte aber klar geworden sein.



  • geht so leider nicht, da std::stringstream auch wieder ein precision hat...
    Mein Ansatz (nach deiner Idee ^^) wäre so etwas in der Richtung:

    #include <cmath>
    #include <iostream>
    #include <sstream>
    #include <string>
    
    template<typename T>
    class precise
    {
    private:
    	int num;
    	T data;
    
    	static void set_prec_helper(std::stringstream &ss, int mantisse)
    	{
    		double tmp = std::pow(2., double(mantisse));
    		int prec = int(std::log(tmp));
    		ss.precision(prec);
    	}
    
    	static void set_prec(std::stringstream &ss)
    	{
    		set_prec_helper(ss, 0);
    	}
    public:
    	precise(int i): num(i) {}
    
    	precise& operator() (const T &_data)
    	{
    		data = _data;
    		return *this;
    	}
    
    	friend std::ostream& operator<< (std::ostream& stream, const precise &obj)
    	{
    		std::stringstream s;
    		obj.set_prec(s);
    		s << obj.data;
    		std::string tmp = s.str();
    		std::string::size_type len_to_point = tmp.find('.');
    		if(len_to_point != std::string::npos)
    		{
    			std::string::size_type len = len_to_point+2+obj.num;
    			if(len < tmp.size())
    				tmp.erase(tmp.begin()+len, tmp.end());
    		}
    		return stream << tmp;
    	}
    }; 
    
    template <>
    void precise<double>::set_prec(std::stringstream &ss)
    {
    	set_prec_helper(ss, 52);
    }
    
    template <>
    void precise<float>::set_prec(std::stringstream &ss)
    {
    	set_prec_helper(ss, 23);
    }
    
    int main()
    {
    	precise<double> not_rounded(10);
    	std::cout << not_rounded(1.2345678) << std::endl;
    	std::cout << not_rounded(1.9999999) << std::endl;
    	std::cout << not_rounded(1.00001) << std::endl;
    	std::cout << not_rounded(1) << std::endl;
    
    	precise<int> not_rounded2(1); //template-fähig sollte es ja schon sein...
    	std::cout << not_rounded2(1234) << std::endl;
    
    	system("PAUSE");
    }
    

    Allerdings ist es jz eben auch nicht ungerundet - nur so, wie es intern gespeichert ist...
    Ne Traumlösung ist es also auf gar keinen Fall...
    Wenn du es genau haben möchtest, musst du halt mit ganzen Zahlen rechnen und dann das Komma noch iwo einfügen...
    Was mir auch gar nicht gefällt, ist die Funktion set_prec_helper ... Das ständige rumgecaste ist echt lästig - man könnte es auch mit nem unsigned long long und dem shift-operator implementieren und dann halt mit /= 10 war mir aber zu viel gefrickel und man würde sich auf sizeof(long long) als mantissenlänge beschränken - der Typ (den es genau genommen gar nicht gibt), ist zwar mit 64bit lang genug für double und float, aber schon bei long double hört es auf, wenn der nicht gerade so wie im msvc implementiert ist...

    bb


Anmelden zum Antworten