gibt es SGN-Funktion in C?



  • TactX schrieb:

    Ist ja aber trivial zu implementieren.

    meinst du?



  • ich hab jetzt einen code gefunden:

    #define SGN(x) (x == 0 ? 0 : x > 0 ? 1 : -1)

    ist schneller wie z.B:

    #define SGN(x) ((x>0)-(x<0))



  • TheShadow2000 schrieb:

    ich hab jetzt einen code gefunden:

    #define SGN(x) (x == 0 ? 0 : x > 0 ? 1 : -1)

    ist schneller wie z.B:

    #define SGN(x) ((x>0)-(x<0))

    glaub' ich nicht. für konstante werte vielleicht, aber letzteres ist immerhin 'branch free' (naja, doch nicht immer) 😞
    :xmas2:



  • ich hab es getestet - 1. version war 10x schneller (mit mingw).

    liegt wohl an integer-arithmetik, da bei der 2. version 2 werte abgezogen werden - während die 1. nur werte vergleicht...



  • ich kriegs leider nur für c++ hin:

    #include <memory>
    
    class Sgn {
    	private:
    		template<class T>
    		static std::auto_ptr<Sgn> createSignObjectByNr( T n );
    
    	public:
    		virtual int getSign() const = 0;
    
    		template<class T>
    		static T sign( T n );
    };
    
    class SgnPositiv : public Sgn {
    	public:
    		int getSign() const {
    			return( 1 );
    		}
    };
    
    class SgnNegativ : public Sgn {
    	public:
    		int getSign() const {
    			return( -1 );
    		}
    };
    
    class SgnNull : public Sgn {
    	public:
    		int getSign() const {
    			return( 0 );
    		}
    };
    
    template<class T> std::auto_ptr<Sgn> Sgn::createSignObjectByNr( T n ) {
    	std::auto_ptr<Sgn> ret( new SgnNull() );
    
    	if( n < T(0) )
    		ret = std::auto_ptr<Sgn>( new SgnNegativ() );
    
    	if( n > T(0) )
    		ret = std::auto_ptr<Sgn>( new SgnPositiv() );
    
    	return( ret );
    }
    
    template<class T> T Sgn::sign( T n ) {
    	std::auto_ptr<Sgn> sobj = Sgn::createSignObjectByNr<T>( n );
    	return( T( sobj.get()->getSign() ) );
    }
    
    // test
    #include <iostream>
    
    int main() {
    	std::cout << "-5 -> " << Sgn::sign( -5 ) << std::endl;
    	std::cout << "+6 -> " << Sgn::sign( 6 ) << std::endl;
    	std::cout << " 0 -> " << Sgn::sign( 0 ) << std::endl;
    }
    


  • ten schrieb:

    TactX schrieb:

    Ist ja aber trivial zu implementieren.

    meinst du?

    Jup.



  • Only-Olli: ich werde es mal bei thedailywtf melden.



  • Only-Olli schrieb:

    ich kriegs leider nur für c++ hin:

    :open_mouth:  :open_mouth:  :open_mouth:  :open_mouth:
    

    macht man das wirklich so in c++ 😃

    mein vorschlag (für ints <= 32 bit):

    #define SGN(x) (((x)>>30)|1)
    


  • @Only-Olli... wow das ist overhead pur...



  • ten schrieb:

    Only-Olli schrieb:

    ich kriegs leider nur für c++ hin:

    :open_mouth:  :open_mouth:  :open_mouth:  :open_mouth:
    

    macht man das wirklich so in c++ 😃

    mein vorschlag (für ints <= 32 bit):

    #define SGN(x) (((x)>>30)|1)
    

    Deine Methode ist krasser! 😃 😃 😃
    Bei negativen Zahlen liefert sie immer 3 (int = 32 Bit)
    Bei positiven Zahlen liefert sie 1 und wenn x == 0 auch 1



  • egon2 schrieb:

    Bei negativen Zahlen liefert sie immer 3 (int = 32 Bit)

    dann haste was falsch gemacht 😉

    egon2 schrieb:

    ...und wenn x == 0 auch 1

    richtich, 'ne 0 hat ja auch kein vorzeichen.
    da kann dieses makro auch nix für 😉



  • ten du troll, mach die leute nicht wuschig!
    das vorzeichenbit bei 32 bit signed ints ist (1<<31) und wenn einer mit embedded geschichten kommt, wirst du geteert und gefedert.



  • @ten: wollte er nicht auch noch wissen, ob seine zahl ne 0 ist?
    Input: -1
    Output: -1

    Input: 0
    Output 1

    Input 1
    Output 1

    und so fehlt doch noch was in deinem makro 😉



  • c.rackwitz schrieb:

    das vorzeichenbit bei 32 bit signed ints ist (1<<31)...

    ist jemand anderer meinung?

    Jay schrieb:

    @ten: wollte er nicht auch noch wissen, ob seine zahl ne 0 ist?
    Input: -1
    Output: -1

    Input: 0
    Output 1

    Input 1
    Output 1

    und so fehlt doch noch was in deinem makro 😉

    ja, stimmt.
    also entweder
    - man vermeidet, dass dam makro eine 0 gegeben wird
    oder
    - das 'aus 0 mach 1' hat keinen negativen effekt (dann kann man's so lassen)
    oder
    - man baut ein 'conditional' ins makro ein: #define SGN(x) ((x)?(((x)>>30)|1):0)



  • Man muss nicht alles mit Bitshifts machen 😉



  • Voll optimiert ist meine "C++-Methode" (die natürlich Schwachsinn ist ^^), nur 3mal langsamer als das SGN-Makro mit den zwei Vergleichen!... Jah und jetzt kommt ihr! 🙂


Anmelden zum Antworten