在C语言中使用位运算进行向下舍入浮点运算

在C语言中使用位运算进行向下舍入浮点运算,c,floating-point,bit-manipulation,C,Floating Point,Bit Manipulation,我试图用C语言中的位运算对浮点进行取整。 我首先将浮点转换为无符号整数。 我认为我的策略应该是先得到指数,然后再把后面的位归零,但我不知道如何编写代码。这就是我到目前为止所做的: float roundDown(float f); unsigned int notRounded = *(unsigned int *)&f; unsigned int copy = notRounded; int exponent = (copy >> 23) & 0xff; int f

我试图用C语言中的位运算对浮点进行取整。 我首先将浮点转换为无符号整数。 我认为我的策略应该是先得到指数,然后再把后面的位归零,但我不知道如何编写代码。这就是我到目前为止所做的:

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. 
float向下舍入(float f)应该是
浮点舍入(float f){

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

下面是一个工作函数,可以四舍五入到二的幂:

#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));
}

因为这只是为了好玩,我不确定限制条件是什么,这里有一个变量适用于负数:

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;
}
float myRoundDown_1(float v){//仅适用于正数

返回((v-0.5f)+(1floorf(),roundf())相关函数也可以这样做。这是家庭作业吗?对我来说似乎不太实际。不,不是家庭作业,我正在尝试学习C中的逐位运算,这是教科书上的一个练习。我已经努力学习了几个小时,如果我能让它工作就好了。你可能需要把所有的尾数bi都归零,部分或没有尾数bits,取决于指数的值。你有没有看过,例如,它显示了浮点的结构?还有,你的意思是“向零舍入”还是“向无限舍入”?看起来像是一本糟糕的书,最好是教有用的信息。通常你只使用一个函数,不必在不必要的时候做点摆弄。谢谢奥利,但我看到了那一页。我了解浮点的结构,包括有符号位、指数和Mantesa。我不知道如何将位归零。为什么我们从分形中取4位ion?(&0xFFF8,前9是符号和指数)@dexter4712345有一个打字错误(现在已修复)。它仍然有效,因为我数了零,而不是一(零的数目是正确的;我写了
0xfff80000
。计算是用64位整数完成的,因为这个常数不能用32位表示,但它起作用了)。谢谢,这非常有帮助。我现在明白了,主要操作是按位&。如何修改以处理负数?例如,如何将-1.5取整为-2?@user2057841将负数取整为-inf的二次幂确实更复杂。对于已经有负数的数,必须做一个特例一个0有效位(返回相同的数字而不作更改),对于其他数字,将一个添加到指数中。我认为,将一个添加到指数中可以在使用
+0x00800000
处理整数表示时完成。@Pascal notRounded&0xFF800000,是的,这更有意义。
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;
}