-2

With the data type "union", I can convert a float to an int. Like this:

#include <stdio.h>
#include <stdlib.h>

int float_as_int(float f)
{
    union { int i; float f; } u;
    u.f = f;
    return u.i;
}

int main() {
    float f = 1.01;
    printf("float = %f\n", f);
    printf("int   = %d\n", float_as_int(f));
    system("pause");
}

The result of this code is:

float = 1.010000
int   = 1065437102

However, from this value "1065437102" how can I get the information about the float it represents. For example: The 32-bit number which it stores and position the "point" (fixed point on the base 2)?

EDIT: The answer to that question was asked here -> How to get the sign, mantissa and exponent of a floating point number

Community
  • 1
  • 1
Mano-Wii
  • 592
  • 5
  • 19
  • 1
    `float` isn't a fixed point format, that's your problem. – πάντα ῥεῖ Jan 02 '16 at 03:45
  • I think the float format used to be considered hw dependent, and non-portable. There are still multiple standards for memory layout. I think the union approach results in undefined behaviour. Recommend you use available conversion. Be sure to measure your performance, and I doubt you can do better than what is available from your tools. Good luck. – 2785528 Jan 02 '16 at 03:48
  • 1
    It's architecture-dependent, but in all likelihood it's [IEEE 754 single-precision](https://en.wikipedia.org/wiki/Single-precision_floating-point_format). What architecture are you interested in? – Mark Plotnick Jan 02 '16 at 03:48
  • 2
    I don't think you can do it in C in a clean, portable way. For platform and compiler dependent hacks, see http://stackoverflow.com/questions/15685181/how-to-get-the-sign-mantissa-and-exponent-of-a-floating-point-number, http://stackoverflow.com/questions/6910115/how-to-represent-float-number-in-memory-in-c etc. – dxiv Jan 02 '16 at 03:52
  • @πάνταῥεῖ, actually I need to study it better. – Mano-Wii Jan 02 '16 at 04:06
  • @MarkPlotnick, I intended to compile the same code for Linux and Windows x64. – Mano-Wii Jan 02 '16 at 04:07
  • BTW, your code won't work on Linux, because `system("pause")` won't work on Linux – Basile Starynkevitch Jan 02 '16 at 04:16
  • @dxiv `frexp()`, mentioned in the answers to some of those questions, is a portable solution. –  Jan 02 '16 at 04:23
  • @duskwuff Correct, but that's C++ only. My comment referred to C specifically. – dxiv Jan 02 '16 at 04:28
  • @dxiv No, `frexp()` doesn't require C++. It's also available in C. –  Jan 02 '16 at 04:32
  • @duskwuff I stand corrected. It looks like `frexp` has always been in ISO C and the `float` overload was standardized in C99. Thank you for the followup. – dxiv Jan 02 '16 at 04:47
  • 1
    `int` is not guaranteed to have 32 bits. `float` neither. Both are not guaranteed to have same endianess. – too honest for this site Jan 02 '16 at 08:16

1 Answers1

1

I would like to get this information because I want to convert floating point to fixed point as quickly as possible.

Just use C casts, e.g. (int)f is compiled to fast code doing the conversion. If you think of fixed point numbers (which C99 don't have natively) you could do e.g.

int percent = (int)(f*100.0);

If you want to understand the actual machine representation of floating point, it is implementation (that is processor and ABI) specific. Read about IEEE floating points (most processors are using them) & endianess. Perhaps you want standard rounding functions, e.g. round, or decomposing functions like frexp.

BTW, I don't think that the C standard guarantees that int and float have the same size and alignment, so your union trick is implementation specific (it does however "work" on x86_64/Linux systems).

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547