使用C中的位操作向下舍入浮点数

时间:2013-02-09 23:20:26

标签: c floating-point bit-manipulation

我正在尝试使用C中的位操作向下舍入浮点数。 我首先将float转换为unsigned int。 我认为我的策略应该是获取指数,然后在那之后将位清零,但我不知道如何编码。这就是我到目前为止所做的:

float roundDown(float f);
unsigned int notRounded = *(unsigned int *)&f;
unsigned int copy = notRounded;
int exponent = (copy >> 23) & 0xff;
int fractional = 127 + 23 - exponent;
if(fractional > 0){
   //not sure how to zero out the bits. 
   //Also don't know how to deal with the signed part. 

2 个答案:

答案 0 :(得分:1)

由于它只是为了好玩,而且我不确定这些约束是什么,这里有一个适用于负数的变体:

float myRoundDown_1 (float v) {        //only works right for positive numbers
    return ((v-0.5f)+(1<<23)) - (1<<23);
}

float myRoundDown_2 (float v) {        //works for all numbers
    static union {
        unsigned long i;
        float f;
    } myfloat;
    unsigned long n;
    myfloat.f = v;
    n = myfloat.i & 0x80000000;
    myfloat.i &= 0x7fffffff;
    myfloat.f = myRoundDown_1(myfloat.f+(n>>31));
    myfloat.i |= n;
    return myfloat.f;
}

答案 1 :(得分:0)

float roundDown(float f);应为float roundDown(float f) {

unsigned int notRounded = *(unsigned int *)&f;与现代编译器优化不兼容。查看“strict aliasing”。

这是一个向下舍入到2的幂的工作函数:

#include <stdio.h>
#include <assert.h>
#include <string.h>

float roundDown(float f) {
  unsigned int notRounded;
  assert(sizeof(int) == sizeof(float));
  memcpy(&notRounded, &f, sizeof(int));

  // zero out the significand (mantissa):
  unsigned int rounded = notRounded & 0xFF800000; 

  float r;
  memcpy(&r, &rounded, sizeof(int));
  return r;
}

int main()
{
  printf("%f %f\n", 1.33, roundDown(1.33));
  printf("%f %f\n", 3.0, roundDown(3.0));
}

这应该产生:

1.330000 1.000000
3.000000 2.000000