Jump to content

Another floating point numbers question (C)

- - - - -

  • Please log in to reply
5 replies to this topic

#1
jcampos8782

jcampos8782

    Learning Programmer

  • Members
  • PipPipPip
  • 49 posts
What exactly does this mean?

3.9225147e-41 

Is this 3.9225147 x 10^-41 ?

Where exactly is this information stored in the bits? From what I understand,
there is a sign bit, 8 exponent bits, and then 23 bits for the fraction... so where the heck is this e information stored?

My assignment is to write a program that takes floating point numbers and display the value of the sign bit, the exponent, and the significand like so:


input 1 = .474747 

sign = +, exponent = -2 significand = 1.e62414 


I have no problems with this a normal decimal float, but as soon as the e is introduced I have no idea what to do.

#2
Alexander

Alexander

    It's Science!

  • Moderators
  • 4,118 posts
  • Location:Vancouver, Eh! Cleverness: 200
You are correct, e-41 = 10 ^ -41

You can gain some insight on what to access and how here; Single precision floating-point format - Wikipedia, the free encyclopedia and maybe here IEEE Standard 754 Floating-Point It does not look all too confusing, but am not sure why there is an assignment like this, unless you are doing some more complex hardware engineering (i.e. PowerPC, some Motorola FPGA devices etc..)

Either way the sign bit is the most significant byte (MSB) to get you started, and it would help to use some low level assembly, i.e. the BSR (bitscan reverse) instruction, although that may be out of scope of your assignment. You should note endianness, x86 is little endian and will appear backwards, 0xabcd will be stored as 0xcd 0xab
Be sure to read the updated FAQ! || Health is achieved through the same 10,000 steps.
If a suggested code/method fails, informing us is less important than telling us why or what errors occurred.

#3
jcampos8782

jcampos8782

    Learning Programmer

  • Members
  • PipPipPip
  • 49 posts
Thank, Ill check out the links. I understand endianness and binary representations of floats, so let me try to explain where I am getting confused a bit better.

If I have the string '3.9225147e-41' I have no problem converting this to the floating point number 3.9225147. But I get stuck understanding what I need to do next. Do I multiply that number by 10.0e-41?

As for the assignment, it is a lower division course at San Jose State University designed to deepen a programmers understanding of the underlying computer system. Much of the class is geared toward learning assembly but we are not quite there.

#4
Alexander

Alexander

    It's Science!

  • Moderators
  • 4,118 posts
  • Location:Vancouver, Eh! Cleverness: 200

Quote

Do I multiply that number by 10.0e-41?
You could, but sscanf can take care of that for you:
char *fpz = "3.9225147e-41";
double fp;
sscanf(fpz, "%lf", &fp);
printf("%e", fp); //3.9225147e-41

I had time to reread what you had asked up there.. The second link should explain things further, for example the exponent bias (127 for single point precision numbers) added to the rest of the base 2 exponent, and the mantissa usually starting with 1.f where f is the binary fraction (which you would convert to scientific notation with the %e specifier I would assume)
Be sure to read the updated FAQ! || Health is achieved through the same 10,000 steps.
If a suggested code/method fails, informing us is less important than telling us why or what errors occurred.

#5
DarkLordofthePenguins

DarkLordofthePenguins

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 409 posts

jcampos8782 said:

What exactly does this mean?

3.9225147e-41 

Is this 3.9225147 x 10^-41 ?

That is correct. It's exponential notation. Floating point types have four parts: the mantissa (whole part), sign of the mantissa, exponent, and size of the exponent. This gives them a much wider range of values, both in terms of numerical value and precision, than integer types.
Programming is a journey, not a destination.

#6
jcampos8782

jcampos8782

    Learning Programmer

  • Members
  • PipPipPip
  • 49 posts

Alexander said:

You could, but sscanf can take care of that for you:
char *fpz = "3.9225147e-41";

double fp;

sscanf(fpz, "%lf", &fp);

printf("%e", fp); //3.9225147e-41
Forgot to mention that I can't use library functions to complete this task. I have completed the assignment... thanks for the help guys!

Solution in case you are bored/interested:

/*

Jason Campos

CS 47

T Howell

Homework Assignment #2

floatparts.c


This program deconstructs a list floating point numbers and displays their parts as:


sign(+/-) exponent(+/- 127) significand( 0 <= s < 2 )


This program assumes a 32 bit float representation and will not work under any other circumstances. 


*/


#include <stdio.h>

#include <stdlib.h>


#define eBias 127

#define eMax 127

#define eMin -127

#define acceptInvalid 0 // set to zero if invalid entries are to be skipped, 1 to throw warnings.


int validateInput(char* fArg, float* fPtr);

int f2l (float f);

int getE(int i);

int getM(int i);

char getSign(int i);



int main(int argc, char* argv[])

{

	if( argc < 2 )

	{

		printf("Usage: floatparts expects a list of floating point numbers in decimal or scientific format.\n");

		printf("Example: floatparts .474747 3.9225147e-41 -3.4028235e+38 \n");

		exit(0);

	}


	int i;

	for (i = 1; i < argc; i++)

	{

		float currInput = 0.0;

		printf("input %i = %s\n", i, argv[i]);


		if (validateInput(argv[i], &currInput)) // returns 0 if input cannot be validated as a float

		{

			int iVal = f2l(currInput);

			char sign = getSign(iVal);

			int  E = getE(iVal);

			int Mr = getM(iVal);

			int Ml = ( E > eMin) ? 1 : 0;


			printf("sign = %c, exponent = %i, significand = %i.%06x\n\n", sign, E, Ml, Mr);

		}

		else

		{

			printf("Argument is not in a recognized floating point format\n");

		}

	}

}


/* Takes a string of characters representing a floating point number

	and converts to an actual float. Stores the value in the space provided 

	by argument 2. 


	returns 1 if valid input, 0 otherwise


	Valid characters for a floating point number are 0-9, +/-, e, and '.'. 

	Only one decimal can be used. 

*/


int validateInput(char* fArg, float* currFloat)

{

		*currFloat =  0.0; // reset

		char* currChar = fArg;

		int decimalSwitch = 0; // 0 if left side, 1 if right

		int negativeSwitch = 1; // 1 or -1

		double divisor = 10.0; 


		while(*currChar != '\0')

		{

			if(!(decimalSwitch)) // Left hand side of decimal accepts only digits or +/-

			{


				if (*currChar >= '0' && *currChar <= '9')

				{

					*currFloat = 10 * (*currFloat) + negativeSwitch * ( *currChar - '0');

				}

				else if (*currChar == '.')

				{

					decimalSwitch = 1;

				}

				else if (*currChar == '-' && *currFloat == 0.0)

				{

					negativeSwitch = -1;

				}

				else

				{

					if (acceptInvalid)

						printf("Invalid character encountered: '%c'. Character skipped.\n", *currChar);

					else

						return 0;

				}

			}

			else // Right hand side of decimal accepts digits and an 'e' preceded by a '+/-'

			{

				if (*currChar >= '0' && *currChar <= '9')

				{

					*currFloat += (negativeSwitch*(*currChar - '0') / (divisor));

					divisor *= 10;

				}

				else if (*currChar == 'e' || *currChar == 'E')

				{

					/* This is an argument formatted as x.xxxe(+/-)exp */

					int exp = 0; 

					int neg = 1;


					currChar++; 

					if (*currChar == '-')

					{

						neg = -1;

					}

					

					currChar++;


					while(*currChar != '\0')

					{

						if (*currChar >= '0' && *currChar <= '9')

						{

							exp = 10*exp + neg*(*currChar -'0');

						}

						else

						{

							if (acceptInvalid)

								printf("Warning: Invalid character encountered as exponent: %c", *currChar);

							else

								return 0;

						}

						currChar++;

					}


					if (exp > 0)

					{

						int i;

						for (i = 0; i < exp; i++)

							*currFloat *= 10;

					}

					else if (exp < 0)

					{

						int i;

						for (i=exp; i < 0; i++)

							*currFloat /= 10;

					}


					return 1;

				}

				else 

				{

					if (acceptInvalid)

						printf("Warning: Invalid character encountered as exponent: %c", *currChar);

					else

						return 0;

				}

			}

			currChar++;

		}

		return 1;

}


int f2l(float f)

/* convert float to long integer with same bit pattern */

{

  union 

  {

	float ff; 

    int l; 

  } a;

  a.ff = f;

  return a.l;

}


/* Mask all but most significant bit */

char getSign(int i)

{

	int j = (i & 0x80000000);

	j = (j>>31) + 1;

	char c = (j==0) ? '-' : '+';

	return c;

}


/* Mask bits 31 and 0-22 */

int getE(int i)

{

	int j = (i & 0x7f800000);

	j>>=23;

	j = j & 0x000000FF; // in the case of a negative number, avoid leading 1s  

	j -= eBias;

	return j;

}


int getM(int i)

{

	int j = (i & 0x007fffff);

	j <<=1 ; // fill empty bit

	return (j);

}





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users