价格的精度处理在程序中至关重要,在WooCommerce中就有一连串的函数对价格进行精度操作。我提取出来是这样的,可以在任何程序中使用:
<?php// 消毒function sanitize_text( $str, $keep_newlines = false ) {if ( is_object( $str ) || is_array( $str ) ) {return '';}$filtered = (string) $str;if ( stripos($filtered, '<') !== false) {$filtered = str_replace( '<', '<', $filtered );$filtered = preg_replace( '@<(script|style)[^>]*?>.*?</\1>@si', '', $filtered );$filtered = strip_tags( $filtered );$filtered = str_replace( "<\n", "<\n", $filtered );}if ( ! $keep_newlines ) {$filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered );}$filtered = trim( $filtered );// Remove percent-encoded characters.$found = false;while ( preg_match( '/%[a-f0-9]{2}/i', $filtered, $match ) ) {$filtered = str_replace( $match[0], '', $filtered );$found = true;}if ( $found ) {// Strip out the whitespace that may now exist after removing percent-encoded characters.$filtered = trim( preg_replace( '/ +/', ' ', $filtered ) );}return $filtered;}function get_price_decimals(){//小数点位数return 0;}function get_price_decimal_separator(){//小数点分割符return '.';}function get_rounding_precision() {// 精度+2,最小值为6$precision = get_price_decimals() + 2;if ( $precision < absint( 6 ) ) {$precision = absint( 6 );}return $precision;}function price_format_decimal( $number, $dp = false, $trim_zeros = false ) {// 价格格式化$number = $number ?? '';$locale = localeconv();$decimals = array( get_price_decimal_separator(), $locale['decimal_point'], $locale['mon_decimal_point'] );// Remove locale from string.if ( ! is_float( $number ) ) {$number = str_replace( $decimals, '.', $number );// Convert multiple dots to just one.$number = preg_replace( '/\.(?![^.]+$)|[^0-9.-]/', '', sanitize_text($number) );}if ( false !== $dp ) {$dp = intval( '' === $dp ? get_price_decimals() : $dp );$number = number_format( floatval( $number ), $dp, '.', '' );} elseif ( is_float( $number ) ) {// DP is false - don't use number format, just return a string using whatever is given. Remove scientific notation using sprintf.$number = str_replace( $decimals, '.', sprintf( '%.' . get_rounding_precision() . 'f', $number ) );// We already had a float, so trailing zeros are not needed.$trim_zeros = true;}if ( $trim_zeros && strstr( $number, '.' ) ) {$number = rtrim( rtrim( $number, '0' ), '.' );}return $number;}<?php // 消毒 function sanitize_text( $str, $keep_newlines = false ) { if ( is_object( $str ) || is_array( $str ) ) { return ''; } $filtered = (string) $str; if ( stripos($filtered, '<') !== false) { $filtered = str_replace( '<', '<', $filtered ); $filtered = preg_replace( '@<(script|style)[^>]*?>.*?</\1>@si', '', $filtered ); $filtered = strip_tags( $filtered ); $filtered = str_replace( "<\n", "<\n", $filtered ); } if ( ! $keep_newlines ) { $filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered ); } $filtered = trim( $filtered ); // Remove percent-encoded characters. $found = false; while ( preg_match( '/%[a-f0-9]{2}/i', $filtered, $match ) ) { $filtered = str_replace( $match[0], '', $filtered ); $found = true; } if ( $found ) { // Strip out the whitespace that may now exist after removing percent-encoded characters. $filtered = trim( preg_replace( '/ +/', ' ', $filtered ) ); } return $filtered; } function get_price_decimals(){//小数点位数 return 0; } function get_price_decimal_separator(){//小数点分割符 return '.'; } function get_rounding_precision() {// 精度+2,最小值为6 $precision = get_price_decimals() + 2; if ( $precision < absint( 6 ) ) { $precision = absint( 6 ); } return $precision; } function price_format_decimal( $number, $dp = false, $trim_zeros = false ) {// 价格格式化 $number = $number ?? ''; $locale = localeconv(); $decimals = array( get_price_decimal_separator(), $locale['decimal_point'], $locale['mon_decimal_point'] ); // Remove locale from string. if ( ! is_float( $number ) ) { $number = str_replace( $decimals, '.', $number ); // Convert multiple dots to just one. $number = preg_replace( '/\.(?![^.]+$)|[^0-9.-]/', '', sanitize_text($number) ); } if ( false !== $dp ) { $dp = intval( '' === $dp ? get_price_decimals() : $dp ); $number = number_format( floatval( $number ), $dp, '.', '' ); } elseif ( is_float( $number ) ) { // DP is false - don't use number format, just return a string using whatever is given. Remove scientific notation using sprintf. $number = str_replace( $decimals, '.', sprintf( '%.' . get_rounding_precision() . 'f', $number ) ); // We already had a float, so trailing zeros are not needed. $trim_zeros = true; } if ( $trim_zeros && strstr( $number, '.' ) ) { $number = rtrim( rtrim( $number, '0' ), '.' ); } return $number; }<?php // 消毒 function sanitize_text( $str, $keep_newlines = false ) { if ( is_object( $str ) || is_array( $str ) ) { return ''; } $filtered = (string) $str; if ( stripos($filtered, '<') !== false) { $filtered = str_replace( '<', '<', $filtered ); $filtered = preg_replace( '@<(script|style)[^>]*?>.*?</\1>@si', '', $filtered ); $filtered = strip_tags( $filtered ); $filtered = str_replace( "<\n", "<\n", $filtered ); } if ( ! $keep_newlines ) { $filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered ); } $filtered = trim( $filtered ); // Remove percent-encoded characters. $found = false; while ( preg_match( '/%[a-f0-9]{2}/i', $filtered, $match ) ) { $filtered = str_replace( $match[0], '', $filtered ); $found = true; } if ( $found ) { // Strip out the whitespace that may now exist after removing percent-encoded characters. $filtered = trim( preg_replace( '/ +/', ' ', $filtered ) ); } return $filtered; } function get_price_decimals(){//小数点位数 return 0; } function get_price_decimal_separator(){//小数点分割符 return '.'; } function get_rounding_precision() {// 精度+2,最小值为6 $precision = get_price_decimals() + 2; if ( $precision < absint( 6 ) ) { $precision = absint( 6 ); } return $precision; } function price_format_decimal( $number, $dp = false, $trim_zeros = false ) {// 价格格式化 $number = $number ?? ''; $locale = localeconv(); $decimals = array( get_price_decimal_separator(), $locale['decimal_point'], $locale['mon_decimal_point'] ); // Remove locale from string. if ( ! is_float( $number ) ) { $number = str_replace( $decimals, '.', $number ); // Convert multiple dots to just one. $number = preg_replace( '/\.(?![^.]+$)|[^0-9.-]/', '', sanitize_text($number) ); } if ( false !== $dp ) { $dp = intval( '' === $dp ? get_price_decimals() : $dp ); $number = number_format( floatval( $number ), $dp, '.', '' ); } elseif ( is_float( $number ) ) { // DP is false - don't use number format, just return a string using whatever is given. Remove scientific notation using sprintf. $number = str_replace( $decimals, '.', sprintf( '%.' . get_rounding_precision() . 'f', $number ) ); // We already had a float, so trailing zeros are not needed. $trim_zeros = true; } if ( $trim_zeros && strstr( $number, '.' ) ) { $number = rtrim( rtrim( $number, '0' ), '.' ); } return $number; }
使用也很简单:
$number = 3.59;$decimal_places = get_price_decimals();$formatted_number = price_format_decimal( $number, $decimal_places );$number = 2.948;$decimal_places = 2;$formatted_number = price_format_decimal( $number, $decimal_places );$number = 3.59; $decimal_places = get_price_decimals(); $formatted_number = price_format_decimal( $number, $decimal_places ); $number = 2.948; $decimal_places = 2; $formatted_number = price_format_decimal( $number, $decimal_places );$number = 3.59; $decimal_places = get_price_decimals(); $formatted_number = price_format_decimal( $number, $decimal_places ); $number = 2.948; $decimal_places = 2; $formatted_number = price_format_decimal( $number, $decimal_places );
而根据我查阅资料,最终得出两种处理精度的方式:
$number = 3.59;$decimal_places = 2;$number_format = number_format( floatval( $number ), $decimal_places, '.', '' );$round = round($number*pow(10, $decimal_places))/pow(10, $decimal_places);$number = 3.59; $decimal_places = 2; $number_format = number_format( floatval( $number ), $decimal_places, '.', '' ); $round = round($number*pow(10, $decimal_places))/pow(10, $decimal_places);$number = 3.59; $decimal_places = 2; $number_format = number_format( floatval( $number ), $decimal_places, '.', '' ); $round = round($number*pow(10, $decimal_places))/pow(10, $decimal_places);
最终WooCommerce中的计算函数、与另外两个计算结果一模一样。需要注意的是number_format出的精度只是显示是处理了,但是不会改变其值,与原值比较是一样的,而经过round处理的值会是一个新值,有时候可以搭配起来使用,比如数据库中存在的是6位小数,而只给用户看两位,就可以配合起来使用了。
© 版权声明
THE END
暂无评论内容