C++ declare platform independent 32-bit float

33,254

Solution 1

You're using Qt. which is specific to C++, so I'm not sure why the question is tagged C.

As far as I know, on all platforms where Qt is supported, type float is 32-bit IEEE.

If somebody decides to port Qt to, say, a Cray vector machine with 64-bit float, you're not going to have a 32-bit floating-point type anyway (unless you implement it yourself in software, but I don't see how that would be useful).

There is no <stdfloat.h> / <cstdfloat> corresponding to <stdint.h> / <cstdint>. C and C++ provide float, double, and long double, and imposes minimal requirements on them, but doesn't give you a way to ask for a floating-point type of any specific size.

Your best bet is probably to add something like this in main, or in some function that's guaranteed to be called during program startup:

assert(CHAR_BIT * sizeof (float) == 32);

and perhaps CHAR_BIT == 8 as well if your code implicitly depends on that.

It's unlikely that the assert will ever fire -- and if it does, you've got bigger problems.

You might want to reconsider whether you really need a 32-bit floating type. If your code were running on a system with 64-bit float, how would that fail to meet your requirements?

Solution 2

There isn't such a sized floating point type, but you can always statically assert that the size is 32 bits. Maybe even something as simple as a global char array:

#include <climits>

char static_assert_float32[1 - (2 * ((sizeof(float) * CHAR_BIT) != 32))];

This will fail to compile if float is not 32 bits by declaring an array of negative size.

Solution 3

Most common implementations of C and C++ will use 32 bit float types. If you really need to catch any platforms where that won't be the case you can use the following to throw an error early in the program:

#include <limits.h>
if (sizeof(float) * CHAR_BIT != 32)
    // error code here

Unfortunately I don't know of a way to detect it at compile time, my earlier answer was flawed.

Solution 4

On a platfrom that supports IEEE-754 float it's going to be 32 bit. On platforms that don't, different width will probably be the least of your problems. Bottom line - use float and don't worry.

Solution 5

The Boolean static member constant std::numeric_limits<float>::is_iec559 is true if and only if float conforms to the IEC 559/IEEE 754 floating-point standard. You'll need to #include the header <limits>.

Note that this alone doesn't tell you whether or not float is specifically 32-bit IEEE floating point, just that it is IEEE floating point -- some implementation without 32-bit floating point hardware might, for example, choose float be 64-bit IEEE floating point.

Share:
33,254

Related videos on Youtube

Ilya Kobelevskiy
Author by

Ilya Kobelevskiy

Updated on June 01, 2020

Comments

  • Ilya Kobelevskiy
    Ilya Kobelevskiy almost 4 years

    Is there a way to declare 32-bit floating point value in C++ - ensuring that it will always be 32 bits regardless of platform/compiler?

    I can do that for integers like that:

    #include <stdint.h>
    
    uint32_t var;  //32 bit unsigned integer
    uint64_t var1; //64 bit unsigned integer
    

    is there a way to do something like that for floats? As far as I know,

    float var; //Usually is 32 bit, but NOT GUARANTEED to be 32 bit
    

    is implementation specific, and is not necessarily 32 bit.. (Correct me if I am wrong).

    I am using qt, so if there is any solution using it I would accept it - I couldn't find anything like quint16 for floats (qreal changes size depending on platform).

    • Admin
      Admin over 10 years
      No - some platforms may have decimal floats.
    • David Heffernan
      David Heffernan over 10 years
      What are you going to do with a 32 bit binary floating point data type on a platform without support for that?
    • Mats Petersson
      Mats Petersson over 10 years
      So exactly what do you want to have happen if float isn't 32-bits? One can of course make a check if (sizeof(float) != 4 && CHAR_BITS == 8) PANIC("Not 32-bit float!!!"); - but I'm not sure what you expect the compiler to do instead, if there isn't a 32-bit float...
    • Ilya Kobelevskiy
      Ilya Kobelevskiy over 10 years
      @MatsPetersson - I just want to ensure that float is 32 bit, and not 64 or 16 bit.
    • Mats Petersson
      Mats Petersson over 10 years
      So, are you writing code that is likely to run on really obscure hardware? I mean DSP's and large and ancient mainframes? If not, then I'd say ignore the problem... [I have a feeling that QT won't work well on mainframes anyway, and DSP's tend to be pretty specialized].
    • MSalters
      MSalters over 10 years
      Pointless. Even if you had two floats that are both 32 bits, they still would be incompatible when one has a 23 bits mantissa and the other a 25 bits mantissa. You would need to specify all widths, not just the total.
    • phuclv
      phuclv about 5 years
      Possible duplicate of Fixed-size floating point types
  • Martin R
    Martin R over 10 years
    As far as I know, sizeof() cannot be used in a preprocessor directive.
  • Admin
    Admin over 10 years
    @MartinR why wouldn't it? it's compile-time anyway :p
  • Keith Thompson
    Keith Thompson over 10 years
    @user9000: Because the preprocessor runs before the source code has even been parsed; the sizeof keyword is just an ordinary identifier with no special significance.
  • Martin R
    Martin R over 10 years
    My clang compiler complains: "error: token is not a valid binary operator in a preprocessor subexpression".
  • Mark Ransom
    Mark Ransom over 10 years
    @MartinR I'm sure you're right. I'll update or delete this answer.
  • Void
    Void over 10 years
    The desired affect can be achieved at compile-time with something like typedef typename std::enable_if<sizeof(float)*CHAR_BIT == 32, float>::type float32;, although you'd still have to handle the case when float is not 32 bits.
  • Ilya Kobelevskiy
    Ilya Kobelevskiy over 10 years
    Thanks! Is it certain Qt only runs on 32-bit IEEE? I tagged as C since I use qt but am not limited to it - any solution ensuring float is 32 bit/providing float data type guaranteed to be 32 bit would be fine, including C. I would like floating point to be 32 bit since I write 32bit since I do some pointer casts/arithmetic relying on the data sizes.
  • Keith Thompson
    Keith Thompson over 10 years
    @IlyaKobelevskiy: It's not certain to me, and it's less certain that it will continue to be the case, but it's very likely. Consider not writing code that makes any assumptions about sizeof (float). Otherwise, decide what you want to do if no 32-bit floating-point type is available. Unless you implement 32-bit FP in software (which is likely overkill), you're going to be out of luck -- and an assert is just the way to handle that.
  • peppe
    peppe over 10 years
    You can have compile time checks too -- C++ defines the macros FLT_MIN, FLT_MAX, FLT_MANT_DIG (#include <cfloat>); or in C++11 code you can use a static_assert(numeric_limits<float>::max() <= ...) (or min, etc.) (#include <limits>).
  • Keith Thompson
    Keith Thompson over 10 years
    And what about a platform where float is 32 bits, but with a different format than the one you want? It's difficult to tell just what your requirements are.
  • bstamour
    bstamour over 10 years
    What about std::conditional? using float_type = typename std::conditional<sizeof(float) * CHAR_BIT == 32, float, float32>::type; EDIT: Nevermind. We are defining float32, not using it.
  • Adam Burry
    Adam Burry over 10 years
    Or, more simply, static_assert(sizeof(float) == 4, "require 32-bit floats").
  • MSalters
    MSalters over 10 years
    @Adam: Nope, that fails for CHAR_BIT==16.
  • MSalters
    MSalters over 10 years
    @IlyaKobelevskiy: Some low end ARMs have only double 64 bits IEEE hardware. 32 bits FP can be fairly efficiently emulated in 64 bits., but you have issues similar to the x87 80 bits registers.
  • Adam Burry
    Adam Burry over 10 years
    @MSalters, if I read you correctly, you are correct. What I wrote is true if a byte is not 8-bits. Since sizeof returns the number of bytes. Is that what you mean?
  • MSalters
    MSalters over 10 years
    @AdamBurry: Yes, C++ defines a byte as the size of a char, which is not necessarily an octet (8 bits). Therefore, sizeof(char)==1 everywhere by definition. All other sizes are defined relative to this.
  • Adam Burry
    Adam Burry over 10 years
    @MSalters, static_assert(sizeof(float) == 4 && CHAR_BIT == 8, "require 32-bit floats") Better?
  • Mark B
    Mark B over 10 years
    @Adam Burry That would preclude sizeof(float) == 2 && CHAR_BIT == 16 though.
  • Adam Burry
    Adam Burry over 10 years
    @MSalters, Have you seen such a system? I suppose if a propose (sizeof * CHAR_BIT) you will argue that static_assert is not portable to older compilers?
  • MSalters
    MSalters over 10 years
    Well, there is the obvious static_assert(sizeof(float) * CHAR_BIT == 32, "require 32 bits floats" which makes the 32 obvious and the code portable.