Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将浮点舍入到C中最接近的整数_C - Fatal编程技术网

将浮点舍入到C中最接近的整数

将浮点舍入到C中最接近的整数,c,C,我可能有一个noob问题,但搜索网站并没有发现任何问题。我正在学习用C语言编程,我试图从头开始构建一个函数,将浮点值舍入到最接近的整数,而不使用math.h。这是我的密码: void main() { float b; for(b = 0; b <= 2; b = b + 0.1) { printf("%f ", b); printf("%i ", (int)b); printf("%f ", b -

我可能有一个noob问题,但搜索网站并没有发现任何问题。我正在学习用C语言编程,我试图从头开始构建一个函数,将浮点值舍入到最接近的整数,而不使用math.h。这是我的密码:

void main()
{
    float b;
    for(b = 0; b <= 2; b = b + 0.1)
    {
        printf("%f    ", b);
        printf("%i    ", (int)b);
        printf("%f    ", b - (int)b);
        printf("Nearest: ");
        if((b - (int)b)<0.5)
            printf("%i    ", (int)b);
        else
            printf("%i    ", (int)b + 1);
        printf("Function: %i    ", round_near(b));
        printf("\n");
    }
    getchar();
}

int round_near(float b)
{
    if((b - (int)b)<0.5)
        return(int)b;
    else
        return (int)b + 1;
}
void main()
{
浮球b;

对于(b=0;b当我试图在gcc下编译时,我得到了以下错误:

/tmp/x1.c:23: error: conflicting types for ‘round_near’
/tmp/x1.c:23: note: an argument type that has a default promotion can’t match an empty parameter name list declaration
/tmp/x1.c:16: error: previous implicit declaration of ‘round_near’ was here
您得到的有趣结果是,您的编译器在第一次遇到
round\u near
时不知道它的定义,并假设它是
int round\u near()
。因此这导致了未定义的行为


如果您将
round_移动到main上方
附近,或者在main上方放入声明,您应该会得到预期的结果。

您没有
int round_附近(float b)
的原型,因此您依赖于隐式声明

尝试将此添加到代码中

int round_near (float b); // Prototype

int main(void) // Nitpick: main returns an int!
使用(b)
附近的
round_的隐式声明,
b
被提升为double。但定义假定它是一个浮点,具有不同的二进制布局,因此会得到疯狂的随机结果


你应该确保你的代码在编译时没有任何警告,以避免这种情况。隐式声明在语言中的唯一原因是向后兼容,但过去十年或二十年中的每一个编译器都会警告你编译不好。

像-241…而不是1或2这样的输出通常表示未初始化的整数。。。 但是,只有在将
int main()
函数移到
int main()
之前,或者在
int main()
之前简单地插入该函数的空白定义(如
int round\u near(float b);
)之后,您的代码才能在Linux上使用GNU C编译器(gcc)进行编译,这就是“原型设计”

否则,函数将被“视”为
int round\u near()
(请参见缺少参数定义),因此程序将打印出未初始化的整数

另一方面,这样的实践不会产生可移植的代码,因此如果不进行下面的修改,您的(实际上是C)代码可能会在Visual Studio中编译……但不会使用其他编译器

另一个离题:不要在
循环中使用浮点数。浮点数很讨厌!

很好地回答了OP的直接问题:
int round\u near(…)
的隐含函数签名与
int round\u near(float b)
round\u near(b)的调用不兼容
double
的形式传递
b

简单的解决方案:原型化功能

关于
round\u near()

  • 强制转换为
    int
    会严重缩小合法范围。最好使用
    long

  • 带有负数的一般错误功能。代码应测试符号

  • 下面是一个利用
    long-long
    范围的解决方案,因为它通常大于
    float
    可以精确表示的整数的连续范围。或者OP可以用
    round\u-near()
    替换
    my\u-round()
    大约40%的时间失败

    #include <limits.h>
    #include <stdio.h>
    
    float my_roundf(float x) {
      // Large `float`s typically have no fractional portion to round
      if (x > LLONG_MAX / 2) return x;
      if (x < LLONG_MIN / 2) return x;
      return x > 0 ? (long long) (x + 0.5f) : (long long) (x - 0.5f);
    }
    
    float rand_float(void) {
      union {
        unsigned char uc[sizeof(float)];
        float f;
      } u;
      do {
        unsigned i;
        for (i = 0; i < sizeof(float); i++) {
          u.uc[i] = rand();
        }
      } while (u.f != u.f);  // re-do if NaN encountered
      return u.f;
    }
    
    void my_roundf_test(void) {
      unsigned n = 100000;
      while (n-- > 0) {
        float x = rand_float();
        float ymath = roundf(x);
        // float ymy = round_near(x);
        float ymy = my_roundf(x);
        // Exact half-way cases may fail
        if (ymath != ymy) {
          printf("x:% .9e math:% .9e my:% .9e\n", x, ymath, ymy);
        }
      }
    }
    
    #包括
    #包括
    浮动我的圆圈F(浮动x){
    //大的“float”通常没有整数部分
    如果(x>LLONG_MAX/2)返回x;
    如果(x0?(长-长)(x+0.5f):(长-长)(x-0.5f);
    }
    浮动随机浮动(无效){
    联合{
    无符号字符uc[sizeof(float)];
    浮动f;
    }u;
    做{
    未签名的i;
    对于(i=0;i0){
    浮动x=随机浮动();
    浮点数ymath=roundf(x);
    //浮动ymy=靠近(x)的圆形_;
    浮动ymy=我的整轮f(x);
    //确切的中途案例可能会失败
    如果(ymath!=ymy){
    printf(“x:%.9e数学:%.9e我的:%.9e\n”,x,ymath,ymy);
    }
    }
    }
    
    注意:每一个浮点舍入模式、负零点等都有确切的中途情况,要考虑一个完整的答案。但是把它留到另一天。

    < P>一个简单的代码(<代码>浮点< /代码>将不适用于<代码> int /代码>类型,所以<代码>长隆< /代码>

    长圆形(浮动a){
    长b=a;
    如果(a>=0)
    返回a-b<0.5?b:b+1;
    其他的
    返回b-a<0.5?b:b-1;
    }
    
    工作:不要忘记负片…@EugeneSh。在什么情况下
    (int)b
    会大于
    b
    void main()
    -->
    int main(void)
    我认为这是一个很棒的问题。如果我要教别人C语言中这一晦涩难懂的部分,我最好用这个问题作为例子。请问为什么是未定义的行为?如果在
    int main()之前没有正确定义的原型,你的函数将被称为
    int round\u near()
    而不是
    int-round\u near(1.2)
    。看到区别了吗?b被丢弃,因此参数b没有值=>参数b没有值(int)b,依此类推……这“您的函数将被称为
    int-round\u near()
    而不是
    int-round\u near(1.2)
    ”不正确。C是不同的。问题不是缺少原型,而是
    float
    被提升为
    double
    (参见下面问题C的答案)。如果OP将编码为
    四舍五入(double f)
    即使没有原型,代码也可以正常工作。它仍然是唯一完整的答案。畏缩我没有想到检查我的原型是否包含在内。典型的新手错误。尽管如此,它很有趣,我没有意识到浮点数和双精度点数不容易互换。我认为其中一个只是另一个的较短版本,如int还有一个很长的内部问题,为什么
    intmain(void)
    voidmain()
    好?90%的情况下
    long long round(float a) {
        long long b = a;
        if (a >= 0)
            return a - b < 0.5 ? b : b + 1;
        else
            return b - a < 0.5 ? b : b - 1;
    }