Weebs
Weebs

Reputation: 435

Writing a floating point multiplication function in C

In my Computer Science course I have been assigned to write a function which takes in two floating point arguments and returns the result of their multiplication in the C language

float multiply(float foo, float bar);

I am not allowed to use any libraries or any floating point operations other than the assignment operator =

I understand how floating points are represented in C and I have extracted the exponents and fractions by doing this:

union sp_item { float frep; unsigned irep; };
union sp_item num;
num.frep = foo;
int exponent = ((num.irep >> 23) - 0x7f);
int frac = (num.irep << 9);

I understand that I need to add the exponents (simple enough), and multiply the two fractions. The thing is I have no idea where to get started to multiply the fractions. I was thinking of converting the fraction into its hexadecimal representation as a string (ex: 0.5 would be "80000000"), and writing an algorithm to multiply the bits that way, but since I can't use any of the C libraries I have no idea how I would go about doing that. Could someone point me in the right direction?

Edit: It occured to me that floats might not be represented the same way on all systems. In this course we assume the first bit is the sign, the next 8 bits are the exponent, and the last 23 bits are the fraction.

Edit: This is what I have gotten so far. When I try and multiply the two integers, I just get zero unless I enter (long long)((long long)xRep * (long long)yRep) into my debuggers watch list

#include <stdio.h>
union sp_item
{
  float frep;
  unsigned irep;
};

int main() {
float x = 0.25;
float y = 0.5;
union sp_item xUnion;
union sp_item yUnion;
xUnion.frep = x; yUnion.frep = y;

unsigned xExp = (xUnion.irep >> 23) - 0x7f;
unsigned yExp = (yUnion.irep >> 23) - 0x7f;

unsigned xRep = (xUnion.irep << 9);
unsigned yRep = (yUnion.irep << 9);


xRep = (xRep >> 1) | 0x80000000;
yRep = (yRep >> 1) | 0x80000000;

long long final = (long long)((long long)xRep * (long long)yRep);

printf("iRep: %x * 2^%d\n", xRep, xExp);
printf("iRep: %x * 2^%d\n", yRep, yExp);
printf("%01611x\n", final);
}

Upvotes: 3

Views: 5268

Answers (3)

Alexandre C.
Alexandre C.

Reputation: 57006

24 + 24 < 64, so you can use long long multiplication. Long longs are guaranteed to be big enough to hold numbers from -(2^63-1) to (2^63-1)

Or you can split the number in two part (low order 16 bits + high order 8 bits) and use 32-bit multiplication (note that unsigned long is guaranteed to provide at least 32 bits).

Take care of normalizing the result correctly afterwards.

Upvotes: 0

Ed Heal
Ed Heal

Reputation: 60037

http://en.wikipedia.org/wiki/Floating_point might be useful reading. The mantissa can only have a certain range and you will need to adjust the exponent to take this into account

Upvotes: 0

Graham Borland
Graham Borland

Reputation: 60721

Why not just multiply the fractions (extracted to their int representation) using the integer multiplication operator, *?

Upvotes: 1

Related Questions