资讯专栏INFORMATION COLUMN

[PHP源码阅读]number_format函数

itvincent / 2543人阅读

摘要:上次讲到是如何解析大整数的,一笔带过了的处理,再详细阅读该函数的源码,以下是小分析。总结阅读完这个函数的源码,学习到的是浮动数与字符串的互相转换的实现细节,字符串与浮点数之间的关系较复杂,之后还要继续学习。

上次讲到PHP是如何解析大整数的,一笔带过了number_format的处理,再详细阅读该函数的源码,以下是小分析。

函数原型
string number_format ( float $number [, int $decimals = 0 ] )

string number_format ( float $number , int $decimals = 0 , string $dec_point = "." , string $thousands_sep = "," )

函数可以接受1、2、4个参数(具体可以看代码的实现)。

如果只提供第一个参数,number的小数部分会被去掉,并且每个千位分隔符都是英文小写逗号"," ;
如果提供两个参数,number将保留小数点后的位数到你设定的值,其余同楼上;
如果提供了四个参数,number 将保留decimals个长度的小数部分, 小数点被替换为dec_point,千位分隔符替换为thousands_sep

PHP_FUNCTION(number_format)
// number
// 你要格式化的数字
// num_decimal_places
// 要保留的小数位数
// dec_separator
// 指定小数点显示的字符
// thousands_separator
// 指定千位分隔符显示的字符
/* {{{ proto string number_format(float number [, int num_decimal_places [, string dec_separator, string thousands_separator]])
   Formats a number with grouped thousands */
PHP_FUNCTION(number_format)
{
    // 期望number_format的第一个参数num是double类型的,在词法阶段已经对字面量常量做了转换
    double num;
    zend_long dec = 0;
    char *thousand_sep = NULL, *dec_point = NULL;
    char thousand_sep_chr = ",", dec_point_chr = ".";
    size_t thousand_sep_len = 0, dec_point_len = 0;
    // 解析参数
    ZEND_PARSE_PARAMETERS_START(1, 4)
        Z_PARAM_DOUBLE(num)// 拿到double类型的num
        Z_PARAM_OPTIONAL
        Z_PARAM_LONG(dec)
        Z_PARAM_STRING_EX(dec_point, dec_point_len, 1, 0)
        Z_PARAM_STRING_EX(thousand_sep, thousand_sep_len, 1, 0)
    ZEND_PARSE_PARAMETERS_END();
    switch(ZEND_NUM_ARGS()) {
    case 1:
        RETURN_STR(_php_math_number_format(num, 0, dec_point_chr, thousand_sep_chr));
        break;
    case 2:
        RETURN_STR(_php_math_number_format(num, (int)dec, dec_point_chr, thousand_sep_chr));
        break;
    case 4:
        if (dec_point == NULL) {
            dec_point = &dec_point_chr;
            dec_point_len = 1;
        }
        if (thousand_sep == NULL) {
            thousand_sep = &thousand_sep_chr;
            thousand_sep_len = 1;
        }
        // _php_math_number_format_ex
        // 真正处理的函数,在本文件第1107行
        RETVAL_STR(_php_math_number_format_ex(num, (int)dec,
                dec_point, dec_point_len, thousand_sep, thousand_sep_len));
        break;
    default:
        WRONG_PARAM_COUNT;
    }
}
/* }}} */
代码执行流程图

_php_math_number_format_ex

函数实现的各种参数数量,最终都会调用_php_math_number_format_ex函数。函数主要做的是:

处理负数;
根据要保留的小数点对浮点数进行四舍五入;
调用strpprintf函数将浮点数表达式转成字符串表示;
计算需要分配给结果变量的字符串长度;
将结果拷贝到返回值中(如果有千位符,则进行千位符分割)

strpprintf

这个函数是实现浮点数与字符串的转换,如上文所说,最终是调用了php_conv_fp函数做的转换(这里是通过gdb调试做的定位),而php_conv_fp函数,往下追踪,调用的是zend_dtoa函数,

更多细节注解,见github项目提交记录。

总结

阅读完这个函数的源码,学习到的是浮动数与字符串的互相转换的实现细节,字符串与浮点数之间的关系较复杂,之后还要继续学习。

原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

更多精彩内容,请关注个人公众号。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/25882.html

相关文章

  • 自上而下,逐步揭开PHP解析大整数的面纱

    摘要:而这个类型的最终之所以输出为,是因为进行科学计数法之后的精度丢失了,重新转成时就恢复不了原来的值。此类问题解决方案对于存储,超过最大表示范围的纯整数,在中可以使用保存,在查询出来的时候会将其使用类型保存的。 遇到的问题 最近遇到一个PHP大整数的问题,问题代码是这样的 $shopId = 17978812896666957068; var_dump($shopId); 上面的代码输出...

    qingshanli1988 评论0 收藏0
  • 系统的讲解 - PHP 浮点数高精度运算

    摘要:浮点数类型包括单精度浮点数和双精度浮点数。小结通过浮点数精度的问题,了解到浮点数的小数用二进制的表示。以后,在使用浮点数运算的时候,一定要慎之又慎,细节决定成败。 概述 记录下,工作中遇到的坑 ... 关于 PHP 浮点数运算,特别是金融行业、电子商务订单管理、数据报表等相关业务,利用浮点数进行加减乘除时,稍不留神运算结果就会出现偏差,轻则损失几十万,重则会有信誉损失,甚至吃上官司,我...

    makeFoxPlay 评论0 收藏0
  • php记录

    摘要:获取执行的语句天前月前周前二进制安全简单说就是传入的参数支持二进制数据,包括这种在中表示字符串结束的字符返回由于是非二进制安全,误判为相等返回负数捕捉异常中断脚本执行是否完成异 获取php pdo 执行的sql语句 class MyPDOStatement extends PDOStatement { protected $_debugValues = null; prote...

    tainzhi 评论0 收藏0
  • PHP算法:一个数字平分为N份,并且总值相等

    摘要:有的时候,你可能有这种需求,需要将一个数字分为等份,多余的自动分配给其中一个数字。 有的时候,你可能有这种需求,需要将一个数字分为N等份,多余的自动分配给其中一个数字。 实现方法有如下两种,当然还有其他的,比如截取substr等,有兴趣的可以自己尝试: 第一种方法,采用bc函数,即PHP的数学扩展库bcmath,具体可以点击如下链接查看更多了解 BC数学函数 http://ph...

    Eric 评论0 收藏0
  • PHP 处理金额

    摘要:导语涉及到金额的代码,一定要谨慎处理。所幸的是,金额一般不会有太多的小数。那么存储的时候呢,一言以蔽之,以分为单位进行存储。格式化金额下面是格式化金额的实例格式化金额参考资料关于浮点数你应该知道的浮点数的一个常见问题的解答。 导语 涉及到金额的代码,一定要谨慎处理。刚好最近做了相关的功能,下面大概说一下。 存储 PHP 的浮点数是不能精确计算的,具体的可以看这篇文章。所幸的是,金额一般...

    asce1885 评论0 收藏0

发表评论

0条评论

itvincent

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<