Dividir un número desnormalizado por 2

I am writing an algorithm that divides a floating point number by 2. In the case of the the numbers already being normalized (the exponent bits are > 0), I think the process is pretty straightforward. I think simply decreasing the exponent field by one and then sticking that value back in is a correct approach.

I am having trouble coming up with how to handle a floating point number already being denormalized (exponent bits are all 0's). I understand what a denormalized number is, and believe I generally understand what it means to divide them. I am running the algorithm I write through another program and here is one message I get that confuses me:

Passing the value 0x7fffff to the function returns 3fffff. The function is supposed to return 0x400000.

I don't really understand what is going on here, and why this is supposed to return this specified value. Is there anybody that can try and explain this and why it is supposed to return this value?

My initial approach for handling a denormalized number was to right shift the fraction bits by one (dividing by 2), and that doesn't seem to be the desired procedure.

Esto es lo que tengo:

unsigned float_half(unsigned uf) {

  unsigned exp = uf & (0x7F800000);
  unsigned sign = uf & (0x80000000);
  unsigned fract = uf & (0x007FFFFF);
  // Check for NaN or infinity
  if(exp == 0x7F800000) {
    return uf;
  }
  // Check for denormalized numbers
  if(exp == 0x00000000) {
    // Need to do something here, not really sure...

    return sign | exp | fract;
  } 
  // Check for exponent of 1 (going to a denormalized number changes things)
  if(exp == 0x00800000) {
    fract = (0x00FFFFFF & uf) >> 1;
    return fract | sign;
  }

  exp--;
  exp = exp & (0x7F800000);
  return sign | exp | fract;
}

preguntado el 01 de febrero de 12 a las 03:02

@caf: Aren't I already doing that? Why did you feel it was necessary to mention that? -

Sorry, you are - I was just reacting to your first paragraph of text where you didn't mention the exception for exponent 1, rather than the code where you did. -

@caf: No problem, thanks for the input. -

2 Respuestas

That the function is supposed to return 0x400000 is to meet the round-to-even mode. Here is my function:

unsigned float_half(unsigned uf){
    unsigned sign = uf & (0x80000000);
    unsigned exp = uf >> 23 & 0xff;
    unsigned frac = f & 0x7fffff;

    if(exp == 0xff)
        return uf;
    else if (exp > 1)
        return sign | --exp << 23 | frac;
    else {
        if (exp == 1)
            frac |= 1 << 23;
        if ((frac & 3) == 3)
            frac++;
        frac >>= 1;
        return sign | frac;
    }
}

Otra

unsigned float_half(unsigned uf){
    unsigned sign = uf & (0x80000000);
    unsigned exp_frac = uf & 0x7fffffff;

    if (exp_frac >= 0x7f800000)
        return uf;
    else if (exp_frac > 0x00ffffff)
        return uf + 0xff800000;
    else {
        if ((exp_frac & 3) == 3)
            exp_frac++;
        exp_frac >> 1;
        return sign | exp_frac;
    }
}

contestado el 11 de mayo de 12 a las 13:05

You are probably supposed to round the value in the denormalized case. For 0x7fffff you are cutting off the final 1 bit with the shift. It seems that you are expected to round the value up instead, for example like this:

if(exp == 0x00000000) {
  fract = (0x00FFFFFF & uf) >> 1;
  if (0x00000001 & uf)
    fract++;
  return fract | sign;
}

If you are supposed to round up or down might also depend on the sign.

Respondido 01 Feb 12, 07:02

There is no reason to believe that the desired rounding is not nearest-even, as this is the IEEE 754 default and is compatible with “The function is supposed to return 0x400000 [for 0x7fffff]” in the question. - Pascal Cuoq

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.