Like Tree1Likes

Float that initializes to NaN

This is a discussion on Float that initializes to NaN within the C++ Programming forums, part of the General Programming Boards category; It is easy to just ignore the rest of what you are writing when you start your post with two ...

  1. #16
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,261
    It is easy to just ignore the rest of what you are writing when you start your post with two quite provoking/disparaging statements; you know that, right?
    It is quite easy to write a newbie who says that some of his code "shouldn't generate any error" off as a fool or troll after having the error explained yet here I am still offering support.

    Being a newbie, your opinions regarding how a C++ compiler should behave in relation to the standard is irrelevant. You don't like that? I don't care. Once you have more experience with why the code we are discussing is wrong you'll understand why it must be the way it is.

    I don't think that the statement "base_safe_float<float> shouldn't generate any error here" is wrong; I know for a fact that it wrong; it is not an opinion. You don't like that? You'll just have to get over it; if you are going to be a programmer you'll always not understand a lot of things.

    Apparently my compiler could chose between the two cases and that is actually what matters to me.
    Your compiler did no such thing. The conversion between `int' to `float' or `float' to `int' isn't at all the same situation. The compiler has rules to choose between those when considering an implicit conversion that form a "best fit" situation.

    If it behaves in one way for float it should behave in the same way for the class I'm creating.
    No. It should not; I've told you why.

    I don't know what is correct behavior and which is not (which you seems to know), but I don't want it to change it when I switch type.
    Then do what I told you to do and explicitly cast the zero result (preferably by `static_cast') of a `typedef'.

    Soma

  2. #17
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,261
    It is easy to just ignore the rest of what you are writing when you start your post with two quite provoking/disparaging statements; you know that, right?
    It is quite easy to write a newbie who says that some of his code "shouldn't generate any error" off as a fool or troll after having the error explained yet here I am still offering support.

    Being a newbie, your opinions regarding how a C++ compiler should behave in relation to the standard is irrelevant. You don't like that? I don't care. Once you have more experience with why the code we are discussing is wrong you'll understand why it must be the way it is.

    I don't think that the statement "base_safe_float<float> shouldn't generate any error here" is wrong; I know for a fact that it wrong; it is not an opinion. You don't like that? You'll just have to get over it; if you are going to be a programmer you'll always not understand a lot of things.

    Apparently my compiler could chose between the two cases and that is actually what matters to me.
    Your compiler did no such thing. The conversion between `int' to `float' or `float' to `int' isn't at all the same situation. The compiler has rules to choose between those when considering an implicit conversion that form a "best fit" situation.

    If it behaves in one way for float it should behave in the same way for the class I'm creating.
    No. It should not; I've told you why.

    I don't know what is correct behavior and which is not (which you seems to know), but I don't want it to change it when I switch type.
    Then do what I told you to do and explicitly cast the zero result (preferably by `static_cast') of a `typedef'.

    Soma

  3. #18
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,304
    Something like this:
    Code:
    #ifndef NANFLOAT_H
    #define NANFLOAT_H
    
    #include <cmath>
    #include <iostream>
    
    template<typename T> class nanInit {
    	T value;
    
    public:
    	nanInit() : value(sqrt(T(-1))) {} // I would optimise out the sqrt call in practice.
    	nanInit(T inVal) : value(inVal) {}
    
    	operator T() const { return retVal; }
    
    	nanInit& operator +=(const nanInit &a)
    	{ return *this = value + a; }
    	nanInit& operator -=(const nanInit &a)
    	{ return *this = value - a; }
    	nanInit& operator *=(const nanInit &a)
    	{ return *this = value * a; }
    	nanInit& operator /=(const nanInit &a)
    	{ return *this = value / a; }
    
    	friend std::ostream& operator << (std::ostream &os, const nanInit &a)
    	{ return os << a.value; }
    	friend std::wostream& operator << (std::wostream &wos, const nanInit &a)
    	{ return wos << a.value; }
    
    	friend std::istream& operator >> (std::istream &is, nanInit &a)
    	{ return is >> a.value; }
    	friend std::wistream& operator >> (std::wistream &wis, nanInit &a)
    	{ return wis >> a.value; }
    
    	const nanInit operator + () const
    	{ return *this; }
    	const nanInit operator - () const
    	{ return static_cast<nanInit>(-value); }
    
    	const nanInit operator++ (int) {	// Post Increment operator
    		nanInit result = *this;
    		++*this;
    		return result;
    	}
    	const nanInit& operator++ ()	// Pre Increment operator
    	{ return *this = value+1; }
    	const nanInit operator-- (int) {	// Post Decrement operator
    		nanInit result = *this;
    		--*this;
    		return result;
    	}
    	const nanInit& operator-- ()	// Pre Decrement operator
    	{ return *this = value-1; }
    };
    
    #endif
    To the best of my knowledge, this is everything you need and nothing you don't.
    Last edited by iMalc; 05-17-2012 at 01:37 AM.
    then likes this.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  4. #19
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,304
    Aw nuts, I forgot the #ifdef DEBUG part around the constructor initialisation list of the default constructor.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  5. #20
    Registered User
    Join Date
    Nov 2011
    Posts
    24
    phantomotap, I appreciate your support and you might be right about what you say, but if you want to help people you can't start by offending them.

    Quote Originally Posted by iMalc View Post
    Something like this:

    *Code*

    To the best of my knowledge, this is everything you need and nothing you don't.
    Thanks, it looks great. I haven't got time to try it out now, though, but I will definitely do it later.

  6. #21
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    4,261
    To the best of my knowledge, this is everything you need and nothing you don't.
    Using two implicit conversions to implement the mathematics assignment operators is really freaking weird.

    If you are going that far in the effort you can pretty much get the same behavior by change the implicit conversion to a reference and adding one for the constant reference.

    if you want to help people you can't start by offending them
    O_o

    That's somewhat interesting but I didn't start off in any way that could possibly be considered offensive.

    Soma

  7. #22
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,304
    Quote Originally Posted by phantomotap View Post
    Using two implicit conversions to implement the mathematics assignment operators is really freaking weird.
    Yeah I guess it is. I had another class which made heavy use of the conversions because it needed to, and leaving them implicit seemed tidier in that case.
    In this case though, I should have used a.value directly.

    Oh and I changed my mind about the #ifdef part, it would of course be far better to put the conditional compilation macro around the typedef that either uses this template or a float directly.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  8. #23
    Registered User
    Join Date
    Nov 2011
    Posts
    24
    I tried your class, iMalc, and everything seems to work like it does for floats or doubles, except from the ?: operator, just like for the class I defined.

    Also, I had to change the return value for the conversion operator to value, since it returned retVal which was undefined. And to generate a NaN, on all machines that support IEEE floating point there is a macro defined in <math.h> called NAN that will do that (maybe that is what you would use in practice).

    As of the problem with the ?: operator: I have the following code

    Code:
    ftype a = MIN(b - c, d);
    where b, c and d are ftype objects, where ftype is defined as

    Code:
    typedef nanInit<float> ftype
    and MIN is a macro defined as

    Code:
    #define  MIN(x, y)  ((x) <= (y) ? (x) : (y))
    However, the code won't compile, and the message I'm getting from the compiler is:

    Code:
    error: operands to ?: have different types 'double' and 'pftype'
    Converting d to float works but is bad, because the definition of ftype may change.

    I may instead convert b - c back to ftype, so I have

    Code:
    ftype a = MIN(ftype(b - c), d);
    which is better, because that code is independent of the definition of ftype.

    However, my project is quite small and I have already had to change on 21 places in the code just becase I changed the definition of ftype from float to nanInit<float>. For larger projects, there could be a lot more work than this that would be necessary just for changing the typedef of ftype (or a corresponding typename), which kind of feels unnecessary. Is there really no way to get around this problem?
    Last edited by then; 05-22-2012 at 08:22 AM.

  9. #24
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,304
    I think this has already been somewhat covered. You need to provide arguments that are the same type to ?:
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  10. #25
    Registered User
    Join Date
    Nov 2011
    Posts
    24
    I don't understand. I know Soma said that too, but I didn't have to provide arguments of the same type when ftype was defined as float, since I provided it with a float and an int and it worked. What's the difference here?

Page 2 of 2 FirstFirst 12
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. (float) or (float*) wrt sizeOf()
    By jakemott in forum C Programming
    Replies: 2
    Last Post: 07-19-2009, 08:13 PM
  2. float value
    By munna_dude in forum C Programming
    Replies: 6
    Last Post: 06-22-2007, 11:25 AM
  3. Replies: 8
    Last Post: 07-08-2005, 09:12 AM
  4. initializes all components of failing to false
    By romeoz in forum C++ Programming
    Replies: 21
    Last Post: 08-01-2003, 09:30 PM
  5. Unresolved external 'convert(float, float)'
    By Ipsec Espah in forum C++ Programming
    Replies: 4
    Last Post: 05-21-2003, 10:08 AM

Tags for this Thread


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21