Ok, so you guys have been VERY helpful so far, especially itCbitC, and I definitely appreciate it. I am almost done with the program but have one small problem I can't seem to figure out with division. Here is the relevant code:
Code:
#include <stdio.h>
#include <stdlib.h>
int showmode = 1;
#define ZERO ((uint)0x00000000)
#define SIGNBIT ((uint)0x80000000)
#define EXPONENT ((uint)0x7F800000)
#define FRACTION ((uint)0x007FFFFF)
#define BIT32 ((uint)0x80000000)
#define BIT24 ((uint)0x00800000)
#define PEXP ((uint)0x3F800000)
typedef unsigned int uint;
float doComp(uint *xf1, uint *xf2, char op)
{
// 1: extract and display sign, biased and
// unbiased exponent, plus fraction bit parts
uint SIGN1 = (*xf1 & SIGNBIT) >> 31;
uint SIGN2 = (*xf2 & SIGNBIT) >> 31;
uint EXP1 = ((*xf1 & EXPONENT) >> 23) - 127;
uint EXP2 = ((*xf2 & EXPONENT) >> 23) - 127;
uint FRAC1 = (*xf1 & FRACTION);
uint FRAC2 = (*xf2 & FRACTION);
FRAC1 |= BIT24;
FRAC2 |= BIT24;
float pFRAC1 = ZERO;
float pFRAC2 = ZERO;
uint *temp1 = (uint*)&pFRAC1;
uint *temp2 = (uint*)&pFRAC2;
*temp1 |= (FRAC1 & FRACTION);
*temp2 |= (FRAC2 & FRACTION);
*temp1 |= PEXP;
*temp2 |= PEXP;
printf("\nf1:\t%lf = %c %lf * 2^(%i)\n", *(float*)xf1, SIGN1?'-':'+', pFRAC1, EXP1);
printf("f2:\t%lf = %c %lf * 2^(%i)\n\n", *(float*)xf2, SIGN2?'-':'+', pFRAC2, EXP2);
// 2: compute f1 op f2 at the bit level by
// appropriately shifting and manipulating
// the bit components -- normalize result
float FRES;
uint *RES = (uint*) &FRES;
uint FRACRES;
uint EXPRES;
uint SIGNRES;
*RES = ZERO;
int SHIFT = 0;
if(op == '-')
{
op = '+';
if(SIGN2 == 0)
SIGN2 = 1;
else
SIGN2 = 0;
}
switch(op)
{
case '+':
...
break;
case '*':
...
break;
case '/':
if((*xf2 & FRACTION) == 0 && (*xf2 & EXPONENT) == 0)
{
if((*xf1 & FRACTION) == 0 && (*xf1 & EXPONENT) == 0)
{
*RES |= BIT32;
*RES |= EXPONENT;
*RES |= ((uint)(0x000FFFFF));
break;
}
*RES |= (SIGN1 << 31);
*RES |= EXPONENT;
break;
}
if((*xf1 & FRACTION) == 0 && (*xf1 & EXPONENT) == 0)
break;
if(EXP2 == 128 && (*xf2 & FRACTION) == 0)
{
if(EXP1 == 128 && (*xf1 & FRACTION) == 0)
{
*RES |= BIT32;
*RES |= EXPONENT;
*RES |= ((uint)(0x000FFFFF));
break;
}
break;
}
FRACRES = ZERO;
FRAC1 >>= 8;
FRAC2 >>= 8;
//printf("FRAC1 = %u\nFRAC2 = %u\n", FRAC1, FRAC2);
float TEMP = (float)FRAC1 / FRAC2;
uint *uTEMP = (uint*)&TEMP;
//printf("(float)FRAC1 / FRAC2 = %lf\n", TEMP);
FRACRES = *uTEMP & FRACTION;
FRACRES |= BIT24;
//printf("*uTEMP & FRACTION = %u\n", *uTEMP & FRACTION);
//printf("FRACRES = %u\n", FRACRES);
while(FRACRES < 8388608 && FRACRES != 0)
{
SHIFT--;
FRACRES <<= 1;
}
while(FRACRES > 16777215)
{
SHIFT++;
FRACRES >>= 1;
}
//printf("FINAL FRACRES = %u\n", FRACRES);
EXPRES = EXP1 - EXP2 + 127 + SHIFT;
printf("EXPRES = %i\n", (int)EXPRES - 127);
EXPRES <<= 23;
SIGNRES = SIGN1 ^ SIGN2;
*RES |= SIGNRES << 31;
*RES |= EXPRES;
*RES |= (FRACRES & FRACTION);
break;
}
//printf("RES = %u\n", *SUM);
return FRES;
}
int main(int argc, char *argv[])
{
float f1, f2, r1, r2;
uint *xf1 = (uint *)&f1;
uint *xf2 = (uint *)&f2;
char op;
int stop = 0, nitem;
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%+10.6f = %08x\n", f1, *xf1);
printf("%+10.6f = %08x\n", f2, *xf2);
}
r2 = doComp(xf1, xf2, op);
printf("result: %f (%f)\n", r1, r2);
}
if (nitem != EOF)
printf("input expression format error\n");
}
Now, for some values, the division switch above works fine. But for values like 1 / 5, it'll give me .4 instead of .2. Is there something obvious here I'm missing? I'll be spending more time on this tomorrow, going over it with a fine toothed comb, but any outside help would be appreciated.
Also, I do apologize about the lack of comments. I'm trying to get into the habit of adding them as I go but it isn't easy to remember. Consequently, if the purpose of a piece of code is unclear, ask and I can explain (hopefully).
And yes, the code is a bit messy, but I spent ~10 hours puzzling this out today, so I have no motivation to organize it tonight.... sorry
And of course, thanks again!