1

I got a bit trouble with my c code. I am trying to extract the sign, exponent and the mantissa. So far it worked out for sign and exponent. The problem begins with mantissa. For example, let's take -5.0. 1 bit for sign, 8 bits for the exponent and 23 bits for the mantissa. This is the binary notation of -5.0:

1 10000001 01000000000000000000000

1 = sign

10000001 = exponent

01000000000000000000000 = mantissa.

I wanna return the bits of the mantissa back.

static int fpmanitssa(uint32_t number) {

   uint32_t numbTemp = 8388607;
   number = number & numbTemp;  //bitwise AND, number should be 2097152.

   int numbDiv;
   int leftover;
   char resultString[23];
   size_t idx = 0;

   do {
       numbDiv = number/2;
       leftover = number % 2;
       resultString[idx++] = leftover;
       number = numbDiv;
   } while (number != 0);

 return resultString;

What I get as result are negative numbers. I don't know why it isn't working. Could you please help to find the problem?

regards Hagi

Hagi
  • 87
  • 1
  • 1
  • 5

3 Answers3

1

1) Floating-point numbers have significands (with linear scale, also called the fraction portion), not mantissas (with logarithmic scales).

2) Your function is declared to return an int, but you attempt to return resultString, which is an array of char. An array of char is not an int and cannot be automatically converted to an int.

3) If you did return resultString, it would fail because the lifetime of resultString is only the time during function execution; it cannot be used after the function returns. If you do intend to return characters from the function, it should be declared so that the caller passes in an existing array of suitable size or the function dynamically allocates an array (as with malloc) and returns its address to the caller, who is responsible for eventually deallocating it (with free).

4) If you want to return an int with the bits of the encoded significand, and number contains the encoded floating-point number with the encoded significand in the low bits, then all you have to do is remove the high bits with an AND operation and return the low bits.

5) If the array of char is to form a printable numeral rather than numeric bits, then '0' should be added to each one, to convert it from the integer 0 or 1 to the character “0” or “1”. In this case, you may also want a null character at the end of resultString.

6) The bits are assigned to resultString in order from low bit to high bit, which may be the opposite order from desired if resultString is intended to be printed later. (The order may be fine if resultString will only be used for calculation, not printing.)

7) The above presume you want to return only the encoded significand, which is the explicit bits in the floating-point encoding. If you want to return the represented significand, including the implicit bit, then you need a 24th position, and it is 1 if the exponent is non-zero and 0 otherwise. (And presuming, of course, that the number is not a NaN or infinity.)

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • The reason why I went for resulString is, I thought I could concatenate the bits and return them. I don't really know how to do it in a different way. It is possible to return the bits as an Integer back? – Hagi May 17 '13 at 17:51
  • @Hagi: You receive the bits in an integer, along with other bits. You can return them in an integer. The only job is to return just the bits you want and not the other bits. – Eric Postpischil May 17 '13 at 17:58
  • That's right. I receive an integer and to get the right bits I do a bitwise AND. I do that with the integer 8388607. Then I receive as result 2097152(in this case). I suppose, this is right so far? Now, what I need is the binary notation of 2097152. What is the best way to get the binary notation of that number? Doing that with a loop, as I tried (but where and how to store it?) or how would you proceed? – Hagi May 17 '13 at 18:13
  • @Hagi: Pass a buffer into the routine instead of trying to return a buffer from the routine. – Eric Postpischil May 17 '13 at 18:31
  • I don't understand that, Eric. What do you mean by passing a buffer into the routine? – Hagi May 17 '13 at 18:42
  • I started with C last week. Sry, if I have annoyed you with this sort of questions. – Hagi May 17 '13 at 18:49
  • @Hagi: Change the declaration of the routine to extract the significand to `static void fpsignificand(uint32_t number, char *buffer)`. In the calling routine, define an array of 23 `char` (or 24, if you want a null-terminated string). Pass that array to `fpsignificand` as one of the arguments. In `fpsignificand`, write the bits to that array, not to an array created locally in the function. – Eric Postpischil May 17 '13 at 18:52
  • You mean I should replace 'static int fpmanitssa(uint32_t number)' by 'fpsignificand(uint32_t number, char *buffer)'. Did I understand that right? But I think, I should not change the declaration. Is it not possible to do it just they way it is? – Hagi May 17 '13 at 19:10
  • @Hagi: Your declaration says that `fpmanitssa` returns an `int`. You cannot return an array of `char` in an `int`. You **must** either return the bits in an `int` with your declaration or return the bits in an array of `char` with a different declaration. The choice is yours. – Eric Postpischil May 17 '13 at 19:14
0

For one thing, your function declaration specifies that you are returning an int, but then you return resultString, which is a char*. I think you may be relying on automatic type conversion which is not part of C. To get resultString to even look like what you want, you need to add 0x30 to leftover (0x30 is '0' and 0x31 is '1').

Then you would need to null terminate the string and convert it back to an int with atoi().

The following probably doesn't work exactly as you intend, but includes changes to handle the ascii/integer conversions:

static int fpmanitssa(uint32_t number) {

   uint32_t numbTemp = 8388607;
   number = number & numbTemp;  //bitwise AND, number should be 2097152.

   int numbDiv;
   int leftover;
   char resultString[24] = {0};
   size_t idx = 0;

   do {
       numbDiv = number/2;
       leftover = number % 2;
       resultString[idx++] = leftover + 0x30;
       number = numbDiv;
   } while (number != 0);

 return atoi(resultString);
}
Chad Barth
  • 528
  • 3
  • 11
  • Arrays of `char` are not necessarily intended for printing; they can be used simply as arrays of small integers. And this code puts the digits into `resultString` in reverse order from how they appear in a numeral, so `atoi` cannot convert it as decided. Also, `atoi` converts a decimal numeral to an integer; it will not work with a binary numeral. `resultString` also cannot be used with `atoi` because it is not null-terminated and some of its members may not be assigned values. – Eric Postpischil May 17 '13 at 17:26
  • I agree with all of that, but I don't believe that Hagi was intending to use the resultString as a generic store to be (implicitly) cast into an integer. As the resultString is 23 characters, I believe the intention was to store it as a string of '0' and '1', one char for each bit. As I said, I don't think the function I wrote solves the problem as defined by Hagi, but gets it closer to something that works (just gets rid of the ascii/int conversion issues). – Chad Barth May 17 '13 at 17:33
  • @cebarth Thank you. At least I don't get a negative number, but it doesn't solve my problem. What I intend is to return the bits of the significant back, but it is not quite working out yet. But would it work with an integer array? – Hagi May 17 '13 at 17:54
0

If you happen to be on uClibc or glibc, you can use ieee754.h and the mantissa field, like so

#include <ieee754.h>

static unsigned int fpmanitssa(float number)
{
        ieee754_float x = {.f = number};
        return x.mantissa;
}
hroptatyr
  • 4,702
  • 1
  • 35
  • 38