C语言中的round函数

标签: , , ,

C语言标准库中有没有round函数?答案是,可能有,也可能没有。这取决于你使用的编译器,更准确地说,是编辑器是否支持C99标准。

让我们简单回顾一下C语言标准的历史:C的第一个标准是由美国国家标准协会(ANSI)发布的。虽然这份文档后来被国际标准化组织(ISO)采纳并且ISO发布的修订版也被ANSI采纳了,但名称ANSI C(而不是 ISO C)仍被广泛使用。

C89

1983年,美国国家标准协会组成了一个委员会,X3J11,为了创立 C 的一套标准。经过漫长而艰苦的过程,该标准于1989年完成,并在作为ANSI X3.159-1989 "Programming Language C"正式生效。这个版本的语言经常被称作"ANSI C",或有时称为"C89"(为了区别C99)。

C90

在1990年,ANSI C标准(带有一些小改动)被美国国家标准协会采纳为ISO/IEC 9899:1990。这个版本有时候称为C90。因此,C89C90通常指同一种语言。

C99

在ANSI的标准确立后,C语言的规范在一段时间内没有大的变动,然而C++在自己的标准化创建过程中继续发展壮大。《标准修正案一》在1995年为C语言创建了一个新标准,但是只修正了一些C89标准中的细节和增加更多更广得国际字符集支持。不过,这个标准引出了1999年ISO 9899:1999的发表。它通常被称为C99。C99被ANSI于2000年3月采用。

虽然C99标准已经确立了十多年,但是却没有流行起来。各个公司对C99的支持所表现出来的兴趣不同。当GCC和其它一些商业编译器支持C99的大部分特性的时候,微软和Borland却似乎对此不感兴趣。而且很多人似乎连C99这个标准都没有听说过,现实中广泛使用的C语言标准仍然是C98,ANSI C也似乎成为了C98的代名词。

除了GCC完全兼容C99标准以外,目前大部分C编译器都不支持或者部分支持C99标准。即使是最新的Visual C++ 2010也仅支持一小部分C99,更不用说Windows 98那个年代发布的Visual C++ 6.0了(那时候C99标准都没有)。既然不支持C99,自然也就没有C99新增的标准库函数round。说了那么多废话,还是得自己写一个。我那么懒,当然不会自己去写,到PHP源码中抄了一份,在ext\standard\math.c文件中。

#include <stdio.h>
#include <float.h>
#include <math.h>

#define zend_isinf(a)   ((_fpclass(a) == _FPCLASS_PINF) || (_fpclass(a) == _FPCLASS_NINF))
#define zend_isnan(x)   _isnan(x)

static double php_round(double val, int places) {
    double t;
    double f = pow(10.0, (double) places);
    double x = val * f;
  
    if (zend_isinf(x) || zend_isnan(x)) {
        return val;
    }

    if (x >= 0.0) {
        t = ceil(x);
        if ((t - x) > 0.50000000001) {
            t -= 1.0;
        }
    } else {
        t = ceil(-x);
        if ((t + x) > 0.50000000001) {
            t -= 1.0;
        }
        t = -t; 
    }
    x = t / f;

    return !zend_isnan(x) ? x : t;
}

int main(int argc, char *argv[])
{
    double d = php_round(5.055, 2);
    printf("%f\n", d);
    return 0;
}

需要指出的是_fpclass和_isnan函数并不是C标准库函数,而是VC运行时库中的函数,即VC对C标准库的拓展,不具有可移植性。

赞赏

微信赞赏支付宝赞赏

随机文章:

  1. 批处理技术内幕:重定向与句柄
  2. VB6拾遗:调用C函数(__cdecl调用约定)
  3. VB6拾遗:内联汇编与CallWindowProc函数
  4. VbsEdit正版序列号
  5. VB6拾遗:调用函数指针

留下回复