Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "floatcomp.h"
#define BIT31 ((uint) 0x80000000)
#define BIT30 ((uint) 0x7f800000)
#define BIT22 ((uint) 0x007fffff)
#define BIT0 ((uint) 0x00000000)
#define BIT1 ((uint) 0x00800000)
#define BITALL ((uint) 0xffffffff)
int showmode = 0;
int main(int argc, char *argv[])
{
float f1, f2, r1, r2;
char op;
int stop = 0, nitem;
if ((argc == 2) && (argv[1][0]=='v'))
showmode = 1;
while ((nitem = scanf("%f %c %f", &f1, &op, &f2)) == 3) {
switch (op) {
case '+': r1 = f1 + f2; break;
case '-': r1 = f1 - f2; break;
case '*': r1 = f1 * f2; break;
case '/': r1 = f1 / f2; break;
default:
stop = 1;
break;
}
if (stop) break;
if (showmode) {
printf("\n");
printf("---- standard computation ---------\n\n");
}
printf("%13.6f %c %13.6f = %13.6f\n", f1, op, f2, r1);
uint xf1 = *(uint *)&f1;
uint xf2 = *(uint *)&f2;
if (showmode) {
printf("\n");
printf("---- integer based computation ----\n\n");
printf(" f1: 0x%08x\n", xf1);
printf(" f2: 0x%08x\n", xf2);
printf("\n");
}
r2 = compute(xf1, xf2, op);
if (showmode) {
printf("\n");
}
printf("%13.6f %c %13.6f = %13.6f\n\n", f1, op, f2, r2);
}
if (nitem != EOF)
printf("input expression format error\n");
}
uint unpack(uint n, int *s, int *e, int *f) // extracts the sign bit, exponent string, and the mantissa from the //number
{
*s= (BIT31 & n) >> 31;
*e= (BIT30 & n) >> 23;
*f= (BIT22 & n);
if(*e!=0)
*f = *f | BIT1;
*e = *e - 127;
}
uint pack(int s, int e, int f) // opposite of unpack, puts the disassembled binary back together
{
s = s << 31;
e = (e + 127) << 23;
f = (f & BIT22);
int n = s | e | f;
return (n);
}
int first_nzb(int f) //finds left-most non-zero bit and returns location in the bit
{
int i;
for(i=31;i>=0;i--)
{
if((1<<i) & f)
return (i);
if(i==0)
return(-1);
}
}
void normalize(int k, int *e, int *f) //puts the fraction where it's supposed to be and determines if the exponent //needs to be accordingly increased or decreased.
{
int shift = k - 23;
if (shift > 0)
*f = *f >> shift;
else
*f = *f << (-shift);
*e = *e + shift;
}
float compute(uint n1, uint n2, char op)
{
int shift;
int s1, e1, f1, s2, e2, f2;
int k, n3, f3, s3, e3;
unpack(n1, &s1, &e1, &f1); //extract appropriate parts from the bit numbers
unpack(n2, &s2, &e2, &f2);
if (op == '-')
{
if(n2<0) //if it's a negative number, take two's compliment by toggling numbers and adding one
n2 = ~n2 + 1;
if(f1>f2) //if the number being subtracted from is greater, sign is positive
{
s3=s1;
}
if(f1<f2) //if the number being subtracted is larger, sign is negative
{
s3=s2;
}
}
if(e1 > e2)
{
//if exponent of n1 is larger, use it's exponent and shift fraction 2 the difference between the //exponents
e3 = e1;
f2 = f2 << (e1 - e2);
}
else if(e2 > e1)//if exponent of n1 is larger, use it's exponent
{
//same as last function, just opposite
e3 = e2;
f1 = f1 << (e2 - e1);
}
else if(e1 == e2)
{
if((f1+f2) > 0)
{
e3 = e2 + 1; // if the exponents are equal, but the fraction is greater than 0, shift 1
shift = 1;
}
else
e3 = e2;
}
if(op == '+')
{
s3=s1; //if adding, just pick first sign, because they're both the same
}
f3 = f1 + f2; // add fractions, then call predefined functions to prepare for addition
if(shift==1) f3 = f3 >> 1;
normalize(first_nzb(f3),&e3, &f3);
f3 = f3 & BIT22;
uint x = pack(s3,e3,f3);
float *fp;
fp = &x;
return *fp;
}
I'll admit, I'm a little bit in over my head with this. I usually program in C++, and this is my first experience with bit manipulation commands. I'm sure I'm making some blatant logic error, but I just don't understand the syntax well enough to see what it is. Anyways, the numbers I get are drastically off. Well, the second one at least, obviously the addition done by integer arithmetic (the first number it returns) is correct. This is a lab assignment, and the TA said we could ask outside sources for advice, but, obviously, don't just give me the entire code, or it would defeat the purpose.