[英]PHP - How to validate float number has maximum 2 digits
我必须验证浮点数是否具有最大两位数。
我尝试了很多方法,但在更多或更多情况下都失败了。
最后是:
//fails for 2638655.99
private function hasMoreThanTwoDecimals(string $number): bool
{
$number = abs($number);
$intPart = floor($number);
$floatPart = $number - $intPart;
return (strlen($floatPart) > 4);
}
要么
//fails for 36.62
private function hasMoreThanTwoDecimals(string $number): bool
{
return $number * 100 - floor($number * 100) > 0.00001;
}
您还使用其他什么方法?
您可以使用来分解数字.
delimeter,然后返回第二部分的长度:
$num = 2638655.99;
echo strlen(explode('.',$num)[1]); // Echo 2
从字面上看,如果二进制浮点数在小数点后最多有两个十进制数字,则小数部分必须是.0,.25,.5或.75之一。
尽管打印输出格式可能会将它们隐藏起来,但所有其他二进制浮点数实际上都具有更多的十进制数字。 例如,最接近2638655.99的IEEE 754 64位二进制数是2638655.99000000022351741790771484375,该数字在小数点后有两位以上。
您可以减去整数部分,然后测试其余部分是否为四种可能性之一。
或者,真正的问题可能是如何确定显示数字是否显示小数点后不超过两位数。 如果是这样,请使用适当的方法转换为字符串,然后找到小数点并计算其后的位数,例如此答案中建议的位数。
$res = preg_match("^[+-]?([0]{1}|[1-9]{1}[0-9]*)(\.?[0-9]{1,2})?$", $num) == true;
我认为这将是最好的解决方案。 您可以使用符号(可选)并强制数字仅以一个零开头。
可能:
+0.10
+123.01
-1
123
不可能:
00.0
0001.0
1.
123.123
请注意,如果未找到匹配项,则preg_match
返回0
如果发生false
则返回false
( preg_match )
您无法使用float
数据类型确定确切的小数位数,因为内部表示形式是二进制的。 以二进制形式表示。 0.1无法精确表示。 这就是循环始终应具有整数增量的原因。
for ($i = -1; $i < 1; $i += 0.1) {
if ($i == 0) {
echo "Zero is here!";
}
}
永远不会说“零在这里!” 由于二进制舍入问题。
您已经尝试使用epsilon(一个很小的值)进行保留(这里是函数的重构版本):
private function hasMoreThanTwoDecimals(string $number): bool
{
$epsilon = 0.00001;
return fmod($number * 100, 1.0) > $epsilon;
}
但对于某些值却失败。 在这种情况下,您需要增加epsilon值。
更精确的方法是避免float
并改用字符串表示形式。 这是您最好的选择,因为-根据您的功能签名-您的数字已经表示为字符串。
private function hasMoreThanTwoDecimals(string $number): bool
{
return bcmod(bcmul($number, '100'), '1.0') != 0;
}
这需要将BCMath模块包含在您的PHP中。 支持BCMath和其他解决方案的软件包是brick / math 。
但是,如果您确实只需要查询数字而不进行计算,则可以通过模式匹配来获得所需的结果。
private function hasMoreThanTwoDecimals(string $number): bool
{
// Trailing 0 does not add to number of decimals
$number = $rtrim($number, '0');
return preg_match('~\.\d\d\d~', $number);
}
您可以使用number_format
number_format($number, 2, '.', '');
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.