摘要:上次講到是如何解析大整數的,一筆帶過了的處理,再詳細閱讀該函數的源碼,以下是小分析。總結閱讀完這個函數的源碼,學習到的是浮動數與字符串的互相轉換的實現細節,字符串與浮點數之間的關系較復雜,之后還要繼續學習。
上次講到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
// 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項目提交記錄。
總結閱讀完這個函數的源碼,學習到的是浮動數與字符串的互相轉換的實現細節,字符串與浮點數之間的關系較復雜,之后還要繼續學習。
原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。
更多精彩內容,請關注個人公眾號。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/25882.html
摘要:而這個類型的最終之所以輸出為,是因為進行科學計數法之后的精度丟失了,重新轉成時就恢復不了原來的值。此類問題解決方案對于存儲,超過最大表示范圍的純整數,在中可以使用保存,在查詢出來的時候會將其使用類型保存的。 遇到的問題 最近遇到一個PHP大整數的問題,問題代碼是這樣的 $shopId = 17978812896666957068; var_dump($shopId); 上面的代碼輸出...
摘要:浮點數類型包括單精度浮點數和雙精度浮點數。小結通過浮點數精度的問題,了解到浮點數的小數用二進制的表示。以后,在使用浮點數運算的時候,一定要慎之又慎,細節決定成敗。 概述 記錄下,工作中遇到的坑 ... 關于 PHP 浮點數運算,特別是金融行業、電子商務訂單管理、數據報表等相關業務,利用浮點數進行加減乘除時,稍不留神運算結果就會出現偏差,輕則損失幾十萬,重則會有信譽損失,甚至吃上官司,我...
摘要:有的時候,你可能有這種需求,需要將一個數字分為等份,多余的自動分配給其中一個數字。 有的時候,你可能有這種需求,需要將一個數字分為N等份,多余的自動分配給其中一個數字。 實現方法有如下兩種,當然還有其他的,比如截取substr等,有興趣的可以自己嘗試: 第一種方法,采用bc函數,即PHP的數學擴展庫bcmath,具體可以點擊如下鏈接查看更多了解 BC數學函數 http://ph...
閱讀 961·2021-11-17 09:33
閱讀 421·2019-08-30 11:16
閱讀 2474·2019-08-29 16:05
閱讀 3354·2019-08-29 15:28
閱讀 1399·2019-08-29 11:29
閱讀 1955·2019-08-26 13:51
閱讀 3392·2019-08-26 11:55
閱讀 1211·2019-08-26 11:31