PHP中的价格精度处理

价格的精度处理在程序中至关重要,在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( '<', '&lt;', $filtered );
		$filtered = preg_replace( '@<(script|style)[^>]*?>.*?</\1>@si', '', $filtered );
		$filtered = strip_tags( $filtered );
		$filtered = str_replace( "<\n", "&lt;\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 = 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
喜欢就支持一下吧
点赞13 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称常用语 夸夸
夸夸
还有吗!没看够!
表情代码图片

    暂无评论内容