Storing the value of Serial.println

Hi, I found a code on Arduino forum (given below) which converts a value in IEEE floating point number.

void SerialPrintFloatIeee754(float RealNumber)
{
byte* ArrayOfFourBytes;
ArrayOfFourBytes = (byte*) &RealNumber;

if (ArrayOfFourBytes[3]>=128)
Serial.print("1");
else
Serial.print("0");

Serial.print((ArrayOfFourBytes[3]/64)%2, BIN);
Serial.print((ArrayOfFourBytes[3]/32)%2, BIN);
Serial.print((ArrayOfFourBytes[3]/16)%2, BIN);
Serial.print((ArrayOfFourBytes[3]/8)%2, BIN);
Serial.print((ArrayOfFourBytes[3]/4)%2, BIN);
Serial.print((ArrayOfFourBytes[3]/2)%2, BIN);
Serial.print( ArrayOfFourBytes[3]%2, BIN);
Serial.print((ArrayOfFourBytes[2]/128)%2, BIN);

//Serial.print(" ");
Serial.print((ArrayOfFourBytes[2]/64)%2, BIN);
Serial.print((ArrayOfFourBytes[2]/32)%2, BIN);
Serial.print((ArrayOfFourBytes[2]/16)%2, BIN);
Serial.print((ArrayOfFourBytes[2]/8)%2, BIN);
Serial.print((ArrayOfFourBytes[2]/4)%2, BIN);
Serial.print((ArrayOfFourBytes[2]/2)%2, BIN);
Serial.print( ArrayOfFourBytes[2]%2, BIN);

Serial.print((ArrayOfFourBytes[1]/128)%2, BIN);
Serial.print((ArrayOfFourBytes[1]/64)%2, BIN);
Serial.print((ArrayOfFourBytes[1]/32)%2, BIN);
Serial.print((ArrayOfFourBytes[1]/16)%2, BIN);
Serial.print((ArrayOfFourBytes[1]/8)%2, BIN);
Serial.print((ArrayOfFourBytes[1]/4)%2, BIN);
Serial.print((ArrayOfFourBytes[1]/2)%2, BIN);
Serial.print( ArrayOfFourBytes[1]%2, BIN);

Serial.print((ArrayOfFourBytes[0]/128)%2, BIN);
Serial.print((ArrayOfFourBytes[0]/64)%2, BIN);
Serial.print((ArrayOfFourBytes[0]/32)%2, BIN);
Serial.print((ArrayOfFourBytes[0]/16)%2, BIN);
Serial.print((ArrayOfFourBytes[0]/8)%2, BIN);
Serial.print((ArrayOfFourBytes[0]/4)%2, BIN);
Serial.print((ArrayOfFourBytes[0]/2)%2, BIN);
Serial.println( ArrayOfFourBytes[0]%2, BIN);

return;
}

float x;

void setup()
{
Serial.begin(9600);
x = 147.625;
Serial.print("x=");
SerialPrintFloatIeee754(x);
//delay(2000);
}

void loop()
{
}

The output is x=01000011000100111010000000000000

Now I just want to get this value stored in some string so that I may proceed for the further operation.

Please help me to figure it out.

Why not simply use a union or even a cast to a 32 bit integer?

That's an unbelievably convoluted (and long) way of doing things.

Even a simple for loop would cut down the code size.

Now I just want to get this value stored in some string

Why?
Why increase the storage requirement eight times?

Please use code tags when posting code.

That code doesn't "convert" anything. It prints the four bytes of the floating point number as 32 binary digits. And it does so, in an inefficient almost comedically retarded manner. My suggestion would be to avoid any advice from whatever ridiculous website you found it at.

Somewhat more interesting, would be code which breaks down an displays the actual components of the floating point representation.

do what AWOL said, create a union. This will allow you to "see" the variable as a float or an integer. The benefit here that when you look at it as an integer, the binary representation stays the same as the float. So, to simply get bits, all you have to do it boolean isBitSet = (boolean)(realNumber & (1L << bit));

This code is slightly shorter:

union {
  float f;
  byte c [4];
} u;

void setup ()
  {
  Serial.begin (115200);
  Serial.println ();
  
  u.f = 147.625;
  
  for (int i = 3; i >= 0; i--)
    {
    for (int b = 7; b >= 0; b--)
      Serial.print ((u.c [i] & bit (b)) ? "1" : "0");
    }
  Serial.println ();
  }  // end of setup

void loop () { }

Output:

01000011000100111010000000000000

And to answer the original question, to make it into a string:

union {
  float f;
  byte c [4];
} u;

void setup ()
  {
  Serial.begin (115200);
  Serial.println ();
  
  u.f = 147.625;
  
  char s [33];
  int j = 0;
  
  // for each byte
  for (int i = 3; i >= 0; i--)
    {
    // for each bit
    for (int b = 7; b >= 0; b--)
      s [j++] = (u.c [i] & bit (b)) ? '1' : '0';
    }
  s [32] = 0;  // null terminator
  
  // print the resulting string
  Serial.println (s);
  }  // end of setup

void loop () { }

michinyon:
That code doesn't "convert" anything. It prints the four bytes of the floating point number as 32 binary digits. And it does so, in an inefficient almost comedically retarded manner. My suggestion would be to avoid any advice from whatever ridiculous website you found it at.

lol, a quick search revealed it came from here: how to see the binary representation of a float ? - #9 by auger-f - Syntax & Programs - Arduino Forum

And it looks like it was a quick test. I do not think it was ever intended for real code.

I am a newbie for the arduino, and would like to see what is inside a float variable, ie its binary representation.

However your comment made me laugh.

would like to see what is inside a float variable, ie its binary representation.

This is quite a reasonable question, and the explanation at wikipedia is as good a place to start as any

Actually, it isn't really. It could use a straightforward example. If you want to find out which of the 32 bits in the float are the exponent, the answer to that question seems quite hard to find.

A much better answer for standard 32 bit floats is found here

It includes a useful diagram.

If you look back at your code in the original post, you might notice that it prints the MSB of the second byte ( indexed [2] ), with the first byte ( indexed[3] ). It's not obvious in your output, because you commented out the Serial.print(" "). The reason why, is clearer if you look at the diagram on that wikipedia page.

I wrote this function which will decompose a float, print the components and then re-calculate the value of the float again.

It might be helpful to people curious about how floating point numbers are encoded.

This has been tested on a PC. It compiles for, but has not been tested on an arduino. It may not deal with all the degenerate cases of non-normalised numbers correctly.

void check_float( float f_in )
{
    printf("\nf_in is %f\n", f_in );   
    union XX { float f ; 
               unsigned char b[4] ; 
               unsigned long L ;     } c ;
    c.f = f_in ;
    
    printf("bytes 0 to 3:  %2X %2X %2X %2X\n", c.b[0], c.b[1], c.b[2], c.b[3] );
    printf("bytes 3 to 0:  %2X %2X %2X %2X\n", c.b[3], c.b[2], c.b[1], c.b[0] );   
    
    // For the arduino, the sign bit is the most significant bit of the float 
    // which is the MSB for b[3]
    
    bool neg = c.b[3] & 0x80 ;
    printf("f_in is %s\n", (neg?"negative":"positive"));
    
    unsigned char expo = c.b[3]<<1 ;    // get bits 6..0 of b[3]
    if ( c.b[2] & 0x80 ) expo+= 1 ;     // get the msb from the next byte
    int adj_expo = (int)expo - 127 ;
    
    bool pos_expo = (adj_expo >= 0)?true:false ;
    int expo_mul = 1 ;               // the exponent multiplier or divisor for the final result
    if ( pos_expo )
    {
        for ( int k=0 ; k<adj_expo ; k++ ) expo_mul *= 2 ;
    }
    else
    {
        for ( int k=0 ; k>adj_expo ; k-- ) expo_mul*= 2 ;
    }
    
    printf("Raw exponent is %2x hex   %d decimal     adjusted exponent = %d (decimal)    expo_mul=%d \n", 
        expo, expo, adj_expo,   expo_mul);
    
    //  Put the significand into an unsigned long  and set the implied 1 bit
    unsigned long signi = c.L ;
    signi &= 0x007FFFFF ;    // get rid of the exponent stuff,  keep bits 22..0
    
    
    //printf("Adjusted significand %08X \n", signi);
    
    // Check for special cases
    if ( expo == 0 )
    {
        if ( signi == 0UL )
        {
            printf("The number is zero\n");
            return ;
        }
        else
        {
            printf("Raw exponent is zero,  not a normalized number \n");
            // Continue, but the result might be wrong.
        }
    }
    else if ( expo == 255 )
    {
        if ( signi == 0UL )
        {
            printf("Input value is infinity\n");
            return ;
        }
        else
        {
            printf("Input value is NaN (not a number)\n");
            return ;
        }
    }
    
    // Add the implied 23 bit for the significand
    
    signi |= 0x00800000 ;    // add the implied MSB ( needs to be 0 for un-normalized floats TBD )
    printf("Adjusted significand %08X \n", signi);

    //  Print the non-zero bits of the significand,  along with their decimal and cumulative value
    unsigned long mask = 0x00800000 ;
    double d = 1.0 ;
    double cum = 0.0 ;
    for ( int k=23 ; k>=0 ; k-- )
    {
        if ( signi & mask )
        {
             cum+= d ;
             printf("  bit = %2d    val=%11.8lf   cumulative value = %12.8lf \n", k, d, cum );    
        }
        mask = mask>>1 ;
        d*=0.5 ;
    }
    
    float f_res = cum ;
    if ( pos_expo ) f_res *= expo_mul ;
    else            f_res /= expo_mul ;
    if ( neg ) f_res = -f_res ;
    
    printf("Result: Sign %s times significand %lf %s exponent %d = f_res = %14.8f       f_in was %14.8f \n", 
         ((neg)?("-ve"):("+ve")),  cum,  ((pos_expo)?" multiplied by ":" divided by "), expo_mul, f_res, f_in );
    
    
}

When I tried the code in my Arduino IDE, it just sends some garbage value. Any further suggestion is awaited.

  Serial.begin (115200);

I always use 115200 baud, not 9600 like you had. Using a lower baud rate is like deliberately driving slowly on the freeway.

So since 115200 / 9600 = 12, that is like driving at 8 km/h on the freeway when you are allowed to drive at 100 km/h. Which would you do?

Thanks for your response. I just set the Baud Rate 115200 in the serial monitor and now I am receiving the desired answer.

Now in order to find the HEX value of the substrings of 4 bits each, I am using the code as under
[/quote]
// Your code followed by (in set up itself)
String One = s.substring(0,4);
Serial.println(One);
String two = (s.substring(4,8));
Serial.println(two);
String three = (s.substring(8,12));
Serial.println(three);
String four = (s.substring(12,16));
Serial.println(four);
String five = (s.substring(16,20));
Serial.println(five);
String six = (s.substring(20,24));
Serial.println(six);
String seven = (s.substring(24,28));
Serial.println(seven);
String eight = (s.substring(28,32));
Serial.println(eight);

int value1 = 0;

for ( int i=0 ; i < 4 ; i++ ) {
value1 <<= 1;
value1 += ( One[ i ] == '1' ) ? 1 : 0;
}
Serial.println( value1, HEX );
//similar loop for other 4 bit strings like two, three, four etc.
[/quote]

However this code gives the error as
[/quote]
Conversion3:29: error: request for member 'substring' in 's', which is of non-class type 'char [33]'
Conversion3:31: error: request for member 'substring' in 's', which is of non-class type 'char [33]'
Conversion3:33: error: request for member 'substring' in 's', which is of non-class type 'char [33]'
Conversion3:35: error: request for member 'substring' in 's', which is of non-class type 'char [33]'
Conversion3:37: error: request for member 'substring' in 's', which is of non-class type 'char [33]'
Conversion3:39: error: request for member 'substring' in 's', which is of non-class type 'char [33]'
Conversion3:41: error: request for member 'substring' in 's', which is of non-class type 'char [33]'
Conversion3:43: error: request for member 'substring' in 's', which is of non-class type 'char [33]'

[/quote]

Please help me in improving the code.

s isn't an item of class String.

Please help me in improving the code.

Instead of writing random nonsense and expecting it to work, save yourself some time and get an elementary textbook or an online tutorial for C/C++.

String One = s.substring(0,4);

substring() is not a method that can be applied to an array of char

value1 += ( One[ i ] == '1' ) ? 1 : 0;

Square-brackets indexing is not a syntax which is usually applicable to objects of class String.

Don't just make stuff up. C can be pretty concise, I suggest you learn it.

michinyon:
Square-brackets indexing is not a syntax which is usually applicable to objects of class String.

The String class overloads the subscript operator. Its strange a few people have commented on this, but its a feature found in every string class I've ever used.