Was haltet ihr von diesem Program, das zwei strings als Zahlen interpretiert und addiert?



  • Hi,

    ich habe dieses Program geschrieben das zwei Zahlen die in strings gespeichert sind zusammenzaehlt:

    std::string zahl1  = "15566155151";
    	std::string zahl2 = "1661";
    	auto max_str = std::max(zahl1.length(), zahl2.length());
    	std::string result(max_str.length()+1,'0');
    
    	zahl1 = std::string(std::abs((int)(result.length() - zahl1.length())), '0') + zahl1;
    	zahl2 = std::string(std::abs((int)(result.length() - zahl2.length())), '0') + zahl2;
    
    	bool overflow = false;
    	for (auto ri = zahl1.rbegin(),
    		      rb = zahl2.rbegin(),
    			  rd = result.rbegin(); ri != zahl1.rend(); ++ri, ++rb, ++rd)
    	{
    		int ir = ((*ri) - 48) + ((*rb) - 48) + (overflow? 1 : 0);
    		overflow = false;
    	    auto s = std::to_string(ir);
    		if (ir >= 10)
    		{
    			*rd = s[1];
    			overflow = true;
    		}else
    			*rd = s[0];
    
    	}
    

    Was haltet ihr davon? Ist das gut und fehlerfrei? Oder ist es nicht effizient und schlechtes C++?

    Vielen Dank



  • Abgesehen vom fehlenden main(), kompiliert, linkt und läuft es?



  • Ja es laeuft:

    #include <iostream>
    #include <string>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    
    int main()
    {
    	std::string zahl1  = "15566155151";
    	std::string zahl2 = "1661";
    	auto max_str = std::max(zahl1.length(), zahl2.length());
    	std::string result(max_str+1,'0');
    
    	zahl1 = std::string(std::abs((int)(result.length() - zahl1.length())), '0') + zahl1;
    	zahl2 = std::string(std::abs((int)(result.length() - zahl2.length())), '0') + zahl2;
    
    	bool overflow = false;
    	for (auto ri = zahl1.rbegin(),
    		      rb = zahl2.rbegin(),
    			  rd = result.rbegin(); ri != zahl1.rend(); ++ri, ++rb, ++rd)
    	{
    		int ir = ((*ri) - 48) + ((*rb) - 48) + (overflow? 1 : 0);
    		overflow = false;
    	    auto s = std::to_string(ir);
    		if (ir >= 10)
    		{
    			*rd = s[1];
    			overflow = true;
    		}else
    			*rd = s[0];
    
    	}
    
    	return 0;
    }
    


  • Hallo.

    Was mir auffällt:
    - 48 im Programmcode ist unlesbar und unportabel (Implementierungen müssen dem ASCII-Standard nicht Folge leisten). Besser '0' .
    - Zeile 18 - 23 dürfte fehlerhaft sein. Wie die schriftliche Addition funktioniert:

    9  Lhs
    +9  Rhs
    10  Carry
    ------------
    18  Ergebnis
    

    Die niederwertigste Ziffer des Ergebnisses ist also auch die niederwertigste Ziffer der überflossenen (klingt künstlich) Addition.
    Hier meine Alternative (die auch den teuren temporären String und std::tostring vermeidet) für die Zeilen 16 - 23:

    overflow = ir >= 10; 
    		*rd += ir - (overflow ? 10 : 0);
    

    Statt dem ?: -Operator kann man auch eine if -Bedingung machen wenn man das lesbarer findet.

    Edit: Gänzlich ohne Verzweigungen aber dafür unlesbarer wäre:

    overflow = ir >= 10; 
    		*rd += ir - overflow * 10;
    

    Habe aber gerade keine Lust auszumessen, ob das überhaupt irgendetwas bringt oder ob der Compiler sowieso denselben Code generiert.

    Edit 2:

    • <vector> , <algorithm> und <cmath> brauchst du nicht, <cstdlib> hingegen schon. Resp. auch nicht, da du die std::abs -Aufrufe in den Zeilen 14 und 15 auch nicht brauchst.

Anmelden zum Antworten