4

I want to store an float value in an integer variable and print that integer variable and i want to see the float value itself. Can it be done or not ?

klutt
  • 30,332
  • 17
  • 55
  • 95
Ron
  • 57
  • 1
  • 6
  • 7
    Why you want that? – Sourav Ghosh Jun 07 '19 at 11:30
  • 2
    Only if `sizeof(int) >= sizeof(float)` – Paul Ogilvie Jun 07 '19 at 11:31
  • Check this: https://stackoverflow.com/questions/33445690/union-float-and-int – Renat Jun 07 '19 at 11:31
  • 2
    You could just `memcpy` the float value over the `int` variable, and when you print it, you tell the print function that it's `%f`. But that's undefined behavior all over the place. – Blaze Jun 07 '19 at 11:31
  • one of my friend asked me whether this is possible or not , i tried but i couldnt find solution thats why – Ron Jun 07 '19 at 11:31
  • But printing it will not show the float as an int. To do that, use `printf("%d", (int)floatval);` – Paul Ogilvie Jun 07 '19 at 11:32
  • 4
    Your question is unclear because what you are saying can be interpreted in many ways. Please show us an example with some values to explain what you actually want. – user694733 Jun 07 '19 at 11:35
  • 1
    example : float a = 1.2; int b; b = a; printf("Data %d",b); Result : 1.2 – Ron Jun 07 '19 at 11:42
  • 4
    @Ron `printf("Data %d",b);` can never yiend in an output of `1.2 ` because `%d` will output an integer no matter what. – Jabberwocky Jun 07 '19 at 11:47
  • yes but still that was an example is there by chance any other way – Ron Jun 07 '19 at 11:48
  • @Ron see Broman's answer below. But as he notes it's a bad idea, and there is no reason to do this. – Jabberwocky Jun 07 '19 at 12:06
  • @Ron: assigning a `float` value to an `int` variable truncates the fractional portion - `b` will get the value `1`. If you assign `b` back to a floating point variable, it will get the value `1.0`. Going between `int` and `float` involves a change in representation - the bit patterns for `1` and `1.0` are *very* different. You can store the *bit pattern* for a `float` value in an `int` if the `int` object is wide enough (using `memcpy` or similar), but if you try to print it out using `%d` you'll get a *huge* integer value. `int` and `float` are not fungible. – John Bode Jun 07 '19 at 14:00

5 Answers5

4

If you want to see the bit pattern of your float variable you could do this:

#include <stdio.h>
#include <stdint.h>
#include <string.h>

int main(void) {
    uint8_t bitpattern[sizeof (float)];
    float f = 3.1414;
    memcpy(bitpattern, &f, sizeof (float));

    for (int i = 0; i < sizeof (float); i++)
      printf("%02x ", bitpattern[i]);
}
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
3

I want to store an float value in an integer variable

Well that's a bad start. Nevertheless, if the integer type chosen is wide enough to accommodate the representation of a float, then you can copy the bytes of the float into the integer. memcpy would be one of the better ways to do this with defined results. For example, if float and int are both 32-bit quantities then

float x = 1.2;
int i;
memcpy(&i, &x, sizeof(x));

That's the closest I can think of to storing the value of the float in an integer in a manner that accommodates the full range of float and avoids losing any precision.

and print that integer variable and i want to see the float value itself .

I take you to mean that you want to print a human-readable decimal representation of the float value. There are multiple standard library functions that convert the internal representation of a float to a printable decimal representation, but they all take a float as input, not an integer. You could of course copy the float representation to an object of type float and use that, but that seems to defeat the purpose. Without doing that, however, there is no standard library function that does what you want.

whther it can be done or not ?

Of course it can be done. Although C does not define a way to do it with C's operators and standard library functions, if you assume details of the representation of float then you can write your own function that replicates the needed aspects of (say) printf, though this is decidedly non-trivial. In principle, one could even write code that analyzes the implementation's representation of float so that no assumptions need be made. But that's a heck of a lot of complex code for a result that could better be obtained by just storing float values in float objects.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
2

From comments:

one of my friend asked me whether this is possible or not , i tried but i couldnt find solution thats why

By strictly answering this, you can do like this:

#include <stdio.h>

int main(void) {
    int x; // Here is where we store the data
    float *p = (float*) &x; // Make a float pointer point at the integer
    *p = 42.67; // Pretend that the integer is a float and store the value
    printf("%f\n", *(float*)&x); // Print what's inside x, pretending it's a float
}

It's NOT a good idea to write like this. Do note that this IS undefined behavior, so the C compiler is basically free to produce whatever garbage it wants. It just happens to be one of those cases of undefined behavior where it (almost) always works in practice. At least for the intended target platform. I wrote this answer strictly to show that it is possible, but as I said, it IS UB, and it's not portable.

This will certainly fail if sizeof(float) > sizeof(int), but I think that is implementation defined. If that's the case, pick an integer type that is at least as big as the floating type.

It can be worth mentioning that a similar thing actually exists in the Quake engine. It's called Carmack hack even though it was not John Carmack that came up with it. But those were the days where cpu cycles were more important than portability. The code looks like this (with original comments):

float Q_rsqrt( float number )
{
    long i;
    float x2, y;
    const float threehalfs = 1.5F;

    x2 = number * 0.5F;
    y  = number;
    i  = * ( long * ) &y;                       // evil floating point bit level hacking
    i  = 0x5f3759df - ( i >> 1 );               // what the fuck? 
    y  = * ( float * ) &i;
    y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
//  y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed

    return y;
}
klutt
  • 30,332
  • 17
  • 55
  • 95
  • If you do that, then you produce undefined behavior. There is some reason to hope that the UB will manifest as you describe, but the standard provides no basis for predicting what it will do. – John Bollinger Jun 07 '19 at 12:04
  • @JohnBollinger Yes, but I have already mentioned that it's probably UB. Do you want me to change it to that it actually IS UB? – klutt Jun 07 '19 at 12:19
  • 1
    I think the answer would be improved if it were changed to say that the procedure described *does* have UB and therefore *is* non-portable. – John Bollinger Jun 07 '19 at 12:25
  • @JohnBollinger Done. – klutt Jun 07 '19 at 12:28
1

Is it possible to store an float value in int variable (?)

Use a union.

When the size of a float matches an available uintN_t type, there is no problem.

float a = ...;
// i want to see the float value itself.
printf("%e %a\n", a, a);  // Use exponential notation

// to an integer type
assert(sizeof(float) == sizeof(uint32_t)); 
union {
  float f;
  uint32_t u;
} x = { a };
unsigned long ul = x.u;
// print that integer variable
printf("%lX\n", ul);

// and back again
union {
  float f;
  uint32_t u;
} y = { .u = (uint32_t) ul };
float f = y.f;
printf("%e %a\n", f, f);

Note that printf("%lX\n", ul); will print something that does not have on obvious match to printf("%e %a\n", a, a);.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
1

First of all, remember that the binary representations of int and float values are very different from each other. The representations for the integer value 1 and the floating point value 1.0 don't look anything like each other. Assuming 32-bit int and float and IEEE-754 representation, we get:

  1: 0000 0000 0000 0000 0000 0000 0000 0001 (0x00000001)
1.0: 0111 1111 1000 0000 0000 0000 0000 0000 (0x3f800000)

Assigning a float value to an int object truncates the fractional portion - if you write something like

int b = 1.2f; // 0x3f99999a

the value stored in b is 1 (0x00000001). If you try to assign b back to a float, such as

float f = b;  

then the value stored in f is 1.0 (0x3f800000), not 1.2 (0x3f99999a)

So you cannot store a float value in an int object through simple assignment.

You can store the bit pattern for a floating-point value in an int object if the int is at least as wide as the float, either by using memcpy or some kind of casting gymnastics (as other answers have shown). However, if you try to print that value using printf with the %d conversion specifier, the output won't be a representation of that float value (1.2), it will be a representation of the integer value represented by that bit pattern (1067030938).

There is no safe, well-defined, standard way of storing a floating point value in an integer object and have it be treated like any other floating point object. C may not be as strongly typed as other languages, but it's strong enough such that you have to rely on unsafe hacks to get around it (as have been demonstrated in other answers).

John Bode
  • 119,563
  • 19
  • 122
  • 198