Thread: Converting Double to Float

  1. #1
    Registered User
    Join Date
    Aug 2005
    Posts
    204

    Converting Double to Float

    Does this make x into a float?

    Code:
    double x;
    float y;
    
    y = (float)(x);
    Does this produce any kind of truncation error? This seems so trivial that it should not work. If it is this simple to convert data types, why do we even have to bother with the (float)(x) statement?

  2. #2
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    What do you mean "it should not work?"

    Of couse it works. Thank goodness it does.
    And yes, y will yield a truncated value if x happens to have more significant digits than float can handle.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  3. #3
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    If it is this simple to convert data types, why do we even have to bother with the (float)(x) statement?
    In fact I have good-bad news for you

    The good is that in C++ you don't need to bother with the (T) x syntax anymore, if you don't want to.

    The bad is that in C++ you should do it like so static_cast<T>(x)

    Why? Because you want to make sure everyone sees the value is being explicitly converted. Some of the nastiest and most evil bugs come from the nearly invisible conversions the former syntax provided.

    Of course. You are always free to simply type:

    Code:
    double x;
    float y;
    
    y = x;
    But... yeah, you will sooner or later find yourself in trouble if you do. An explicit conversion doesn't reduce bugs, but it surely helps locating them. Use 'em.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Mario F.
    The good is that in C++ you don't need to bother with the (T) x syntax anymore, if you don't want to.

    The bad is that in C++ you should do it like so static_cast<T>(x)

    Why? Because you want to make sure everyone sees the value is being explicitly converted. Some of the nastiest and most evil bugs come from the nearly invisible conversions the former syntax provided.
    The (T) conversion syntax is still supported by C++. This is one case where either form can be used. It is therefore up to the programmer to exercise the old brain box and decide which form of cast to use. In practice, casting a double to a float is safe (except for loss of precision and loss of range), so there is little or no real benefit to using static_cast to do the conversion.
    Quote Originally Posted by Mario F.
    Of course. You are always free to simply type:

    Code:
    double x;
    float y;
    
    y = x;
    But... yeah, you will sooner or later find yourself in trouble if you do. An explicit conversion doesn't reduce bugs, but it surely helps locating them. Use 'em.
    Either form of cast (eg (float)x or static_cast<float>(x)) are explicit conversions.

    Your example is an implicit conversion. The problem with implicit conversions in this case is that it is an implicit conversion that can lose precision and range of values (double supports greater precision and, on some machines, a greater range of values than a float). So a fair few compilers moan about doing them, by emitting a warning. While it is not an error (in the sense that the code will compile and usually do what is expected) the compiler vendor is doing you a service by issuing a warning, as the conversion loses information that may be important in some applications.

    Casting x to float is an explicit conversion: in situations where a compiler sees an explicit conversion where an implicit one would suffice then, practically with most compilers, the cast achieves no more than telling the compiler not to complain if the conversion is suspicious.

  5. #5
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    I think we were both saying the same thing grumpy
    Maybe I didn't make it clear though.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  6. #6
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Quote Originally Posted by grumpy
    The (T) conversion syntax is still supported by C++. This is one case where either form can be used. It is therefore up to the programmer to exercise the old brain box and decide which form of cast to use. In practice, casting a double to a float is safe (except for loss of precision and loss of range), so there is little or no real benefit to using static_cast to do the conversion.
    Sure there is. First, you avoid the outdated and hard-to-find C syntax. Suppose you later change y to be a double. You need to remove all the conversions. Which is easier to grep for, static_cast or ()?
    Second, static_cast only permits safe casts, while the C cast permits everything. In other words, if you make some mistake, the static_cast is more likely to catch it.
    OK, the above two are not that important in this case. (float) can be searched for rather easily, and there aren't many mistakes one can make here. (double->pointer, for example, is not a valid conversion even using C casts.) But:
    Third, you probably have some other places in the program where you really should use C++ casts. A reinterpret_cast from a WinAPI datatype to a pointer, perhaps? A static_cast from int to char? (Slip and you've typed char* instead of char - not good.) Perhaps a dynamic_cast or two? Consistency is good, so all casts should be C++ if one is.
    Fourth, you should make a habit out of not using C casts. It's the same reason as why I urge people to use for(int i = 0; i < end; ++i) instead of i++. Sure, no self-respecting compiler will make any difference between the two, but using prefix is a good habit when you switch to iterators. It also helps dispell the myth that using prefix increments in the loop updater causes the increment to be performed before the loop body runs.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  7. #7
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by CornedBee
    Sure there is. First, you avoid the outdated and hard-to-find C syntax. Suppose you later change y to be a double. You need to remove all the conversions. Which is easier to grep for, static_cast or ()?
    Use of grep is a poor justification. All shells under unix provide a means of delimiting braces so you can search for them (the means vary with shell, but are typically pretty simple eg prefixing with a \).

    There is also an alternative: not removing the conversions. Converting a type X to type X (eg double to a double) is invariably safe.
    Quote Originally Posted by CornedBee
    Second, static_cast only permits safe casts, while the C cast permits everything. In other words, if you make some mistake, the static_cast is more likely to catch it.
    Uh hu.

    Technically, a C-style cast is equivalent to a combination of static_cast, reinterpret_cast, const_cast, and some elements of dynamic_cast (dynamic_cast involves a run time check, which a C style cast does not as it always happens at compile time). Of the C++ casts, the only really safe one is dynamic_cast, as it can fail at run time and the result of the conversion can be checked.

    In scenarios where a static_cast<> is appropriate, then the static_cast<> is just as unsafe as the C-style cast ...... as they do the same thing. It is a fair call that using static_cast<> instead of a C-style cast does prevent errors (eg allowing conversions that are the goal of reinterpret_cast and const_cast). The other area where static_cast<> will flag an error (and a C-style cast will not) is converting between dissimilar class types or pointers to them (eg converting an X to a Y, when it is not technically possible to convert and X to a Y).

    Quote Originally Posted by CornedBee
    OK, the above two are not that important in this case. (float) can be searched for rather easily, and there aren't many mistakes one can make here. (double->pointer, for example, is not a valid conversion even using C casts.) But:
    double to float is one case where the C-style cast is functionally equivalent to the C++ static cast, and not one of the conversions for which static_cast is inherently safer than a C-style cast.

    All casts are something that the programmer should use carefully. And all are subject to abuse. The message that static_cast is safer, so it should be used, is misleading ...... static_cast is also potentially unsafe.

    While it is true that static_cast is somewhat safer than a C-style cast, I've seen too many people assume that they must be OK because they've been told a static_cast<> is safer than a C-style cast. And then they get bitten by having used static_cast<> unsafely.

    Quote Originally Posted by CornedBee
    Third, you probably have some other places in the program where you really should use C++ casts. A reinterpret_cast from a WinAPI datatype to a pointer, perhaps? A static_cast from int to char? (Slip and you've typed char* instead of char - not good.)
    None of your examples here are particularly good. Using the C++ style casts does not achieve anything that a C-style cast will not. They are all equally unsafe.

    Attempting a conversion to a char * when you intend a conversion to char (or vice versa) is as much of a problem whether you use C or C++ style casts. Which is not much: invariably the result will be a compile time error, as there are only four things you can do with the result of the conversion;

    1) Assign it to a variable.
    2) Pass it as an argument to a function that is expecting that argument to be the original type (char)
    3) Invoke a member function of a class (eg converted_pointer->member_function())
    4) A NOOP. For example, the statement "static_cast<char> x;" which does the conversion but does nothing with the result.

    The first three will yield compile time errors, regardless of whether a C or C++-style cast is used. The only thing that changes is the wording of the error message. Because, in both cases, the conversion can be valid (i.e. the compiler won't complain about it) or it is invalid (i.e. the compiler will complain). If the conversion is valid, the compiler will complain when the result of the conversion is used. The only thing that changes by using a C-style cast or a static_cast is that there are some cases where the C-style cast will succeed and the static_cast will fail .... and those cases will fall through and be caught by the compiler when the result of the conversion is USED.

    The fourth example does nothing, and can be safely ignored (indeed, optimised away) in most circumstances.
    Quote Originally Posted by CornedBee
    Perhaps a dynamic_cast or two?
    The most common usages of dynamic_cast<> it is not possible to use a C-style cast anyway, as a C-style cast does not involve a run-time check.

    Quote Originally Posted by CornedBee
    Consistency is good, so all casts should be C++ if one is.
    That's a stylistic argument, not a technical imperative. But, ignoring that for sake of discussion, consistency needs to have a purpose.

    One could also argue that conversions which are valid in C should remain C-style casts. Particularly if it is desirable to be able to write code that works with either a C or C++ compiler. Having worked in that scenario (developing a library that had to be buildable with both a C compiler and a C++ compiler to suit different customers), we had code with variants for C and C++ of the form
    Code:
    #ifdef __cplusplus    /* standard means of detecting a C++ compiler */
    /*  C++ version */
    #else
    /* C equivalent of the C++ version */
    #endif
    One of our goals, obviously, was to minimise occurrences where we had to do that. Which meant there had to be a demonstrable advantage.

    As it turned out, the only times we had to do this was if we had a reason to exploit the STL in C++ code rather than the C library (eg using std::sort() rather than qsort() was more efficient in some circumstances). Using C-style casts allowed us to avoid code in the C++ and C sections that used a different conversion mechanism to achieve exactly the same thing. So, for example, we wouldn't have had to do this;
    Code:
    #ifdef __cplusplus
       y = static_cast<float>(x)
    #else
       y = (float)x;
    #endif
    as the C-cast is valid in both C and C++.
    Quote Originally Posted by CornedBee
    Fourth, you should make a habit out of not using C casts.
    I agree with you here, but I go further: one should not make a habit of using either C or C++ casts. Or, more specifically, every usage of a cast should be backed up by some analysis that says it is necessary and appropriate (rather than the all-too-common approach of using a cast as a blunt instrument to shut up a moaning compiler). And dynamic_cast<> (the main C++ cast that achieves things that can't be done with a C-style cast) can often be eliminated by design of a class hierarchy and use of polymorphism.

    As a rule of thumb, I generally agree with you that C++ style casts should be used exclusively in C++ code. But that is a stylistic concern (eg trapping errors by inattentive programmers). And, as with all rules of thumb, it is possible to find exceptions where it a good idea to bend or break the rule .... if you analyse what you are doing.

  8. #8
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    For the most part casts are unsafe and often a bad practice. This is true of any programming language that allows explicit conversions. Not just C or C++. This argument could extend to a lot more programming languages. Maybe not so much the "unsafe" bit (certainly not for the higher level languages). But certainly the bad style considerations are true for about any programming language that implements explicit conversions.

    However, they are useful sometimes. And I would even dare to say that a static cast, for example, can prove to be a much more logical and correct approach when the alternative would be having a more obscure and complicated piece of code. (C++ FAQ Lite - 6.16 )

    Where I do believe casts prove their weakness is portability. But if this is not an issue then they can, and should, be used where common sense proves them to be a viable option.

    In this context, C++ style casts prove to be much stronger than the C style. If for nothing else, they are more visible.

    In C++, explicit C style casts show lazyness. Even if they are quite plausible within the context of the code where they were inserted. There are no excuses. This is my humble opinion.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 05-13-2009, 03:25 PM
  2. Debug Error Really Quick Question
    By GCNDoug in forum C Programming
    Replies: 1
    Last Post: 04-23-2007, 12:05 PM
  3. Opengl walking leg animation
    By Bobby230 in forum C Programming
    Replies: 3
    Last Post: 03-05-2006, 03:41 PM
  4. Help with multi function progam
    By WackoWolf in forum C Programming
    Replies: 22
    Last Post: 10-13-2005, 02:56 AM
  5. Multidimensional String
    By Beast() in forum C Programming
    Replies: 14
    Last Post: 07-03-2004, 12:47 AM