Schnellste Quadratzahl



  • Jeder weiß, dass x*x schneller ist als pow(x,2).
    Was ist nun wenn ich f(x)*f(x) berechnen möchte, wobei f(x)
    schon sehr lange braucht?
    Um f(x) nur einmal zu berechnen und nicht den Overhead von pow(x,n) zu haben (Man will ja nicht ne beliebige Potenz, sondern nur die Potenz 2), geht dann sowas:

    (x2 = f(x))*x2
    

    ?

    Gibts da vielleicht in c++ andere Möglichkeiten als in purem c?



  • x = f(x);
    res = x * x;
    

    😕



  • MC schrieb:

    Was ist nun wenn ich f(x)*f(x) berechnen möchte, wobei f(x)
    schon sehr lange braucht?

    Wenn f() ohne Seiteneffekte ist, dann wird wohl jeder das Ergebnis in eine (lokale) Variable speichern, bevor quadriert wird. Und wenn f() eben doch (erwünschte) Seiteneffekte hat, dann muss man es sowieso zweimal ausführen.

    pow() wird man wohl eher für nicht-triviale Fälle verwenden, also Exponent != 2.0 - und da es sowieso Fließkommazahlen sind ist es gar nicht für die einfache Quadratur gedacht.



  • namespace detail {
    template <int N> struct int_tag {};
    template <int N, typename T>
    typename std::remove_reference<T>::type pow_help(int_tag<N>, T&& x) {
      static_assert(N>0, "");
      typename std::remove_reference<T>::type y = pow_help(int_tag<N/2>{}, x);
      return N%2 ? y*y*x : y*y;
    }
    template <typename T>
    T&& pow_help(int_tag<1>, T&& x) {
      return std::forward<T>(x);
    }
    }
    
    template <int N, typename T>
    typename std::remove_reference<T>::type fast_pow(T&& x) {
      static_assert(N>0, "Power must be strictly positive");
      return detail::pow_help(detail::int_tag<N>{}, std::forward<T>(x));
    }
    
    int f() {
      std::cout << "langwierige Berechnung\n";
      return 3;
    }
    
    int main()
    {
      std::cout << fast_pow<2>(f()) << '\n';
    }
    


  • Viel einfacher!!!

    template<typename T>
    T Quadrat(T a){
       return a*a;
    }
    …
    d=sqrt(quadrat(y2-y1)+quadrat(x2-x1));//falls kein _hypot/hypot2 da ist
    


  • MC schrieb:

    geht dann sowas:

    (x2 = f(x))*x2
    

    Nein, da die Auswertungsreihenfolge der Teilausdrücke nicht festgelegt ist.

    Gibts da vielleicht in c++ andere Möglichkeiten als in purem c?

    Bestimmt, aber es geht wohl kaum etwas über eine simple Funktion.



  • Die Idee Templates zu verwenden finde ich gut, aber müssten diese nicht inline definiert sein, um den gewünschten Effet zu haben? Sonst erhält man nach der Instantiierung ja was analoges zu dem da:

    _f(double x){
    return x*x;
    }
    
    _f(f(x))
    


  • MC schrieb:

    Die Idee Templates zu verwenden finde ich gut, aber müssten diese nicht inline definiert sein, um den gewünschten Effet zu haben?

    Da würde ich mich auf den optimierenden Compiler verlassen. Der sollte so einen simplen Funktionsaufruf automatisch inlinen.


Anmelden zum Antworten