假设我们有0.00045。我想找到一种方法来计算小数点后的“有效”零的数量(在这种情况下为3)。我一直在尝试实施strpos
或substr
,但我遇到了问题。
其他exs ....
3.006405:应返回“2”
0.0000062:应返回“5”
9.0100000008:应返回“1”
有什么想法吗?
答案 0 :(得分:5)
strspn($num, "0", strpos($num, ".")+1)
strspn
找到一系列零的长度。 strpos
找到小数点的位置,我们从那个位置开始。
但是,这对0.0000062
不起作用,因为它在转换为字符串时会转换为科学记数法:6.200000e-6
。当数字以e-<exponent>
结尾时,零的数量为<exponent>-1
。您可以使用正则表达式检查这一点。
答案 1 :(得分:1)
我决定研究处理此任务的一些不同可能性。
我必须说,Barmar的解决方案易于阅读,非常适合不受科学计数法影响的浮点数。
作为一个思想实验,我决定制作几个正则表达式来完成相同的工作。 (*即使将整数值传递给正则表达式,方法也仍然有效。)
preg_match_all()
,我正在使用“继续”元字符(\G
)来匹配第一个.0
,然后是零个或多个紧随其后的0
。preg_match()
,我可以更简单地匹配点,然后使用\K
“忘记它”(重新开始全字符串匹配),然后从该位置匹配1个或多个零。不幸的是,这需要另外调用str_len()
。我通常只支持preg_
调用,因为它导致的函数调用少于非正则表达式方法。受https://codereview.stackexchange.com/q/219601/141885的启发,我想编写一个仅使用算术(猜测和检查)来计算小数点后的零的函数。 尽管它没有像其他人那样受科学记法的折磨,但它并不完美,并且在不同的操作系统/版本/环境/ yatta-yatta上的浮点数/整数有一定的限制(我不假装知道所有进出,但我知道还是有区别的。)继续尝试将这些方法与您的项目数据一起使用,并随时就有效和无效的问题发表评论。 ...而且如果您知道为什么我邀请您来教育我:)
最后,在StackOverflow(here's one)上有很多建议使用标准php库BCMath的帖子。
代码:(Demo)
function mathematical_zeros_after_dot($float) {
$float = abs($float); // remove any signs
$float -= (int)$float; // remove whole numbers from float
if ($float == 0) {
return "Rendered as 0";
}
$max = 20;
for ($x = 0; $x < $max; ++$x) { // for loop with a hard limit to avoid infinite loop
$float *= 10;
if ($float >= 1) {
return $x;
}
}
return "$max {exceeded}";
}
$floats = [
25.000000000022, // 10
0.0000062, // 5
0.020320, // 1
.505000, // 0
0, // 0
.000507, // 3
-.002009, // 2
1000, // 0
0.00, // 0
1 // 0
-1.0000000000004000004, // 12
981.0000000000000000000004000004 // 21
];
foreach ($floats as $float) {
echo "(Math) {$float} has " , mathematical_zeros_after_dot($float) , " zero(s)\n";
echo "Barmar {$float} has " , strspn($float, "0", strpos($float, ".")+1) , " zero(s)\n";
echo "(PMA) {$float} has " , preg_match_all('~(?:\.|\G(?!^))0~', $float) , " zero(s)\n";
echo "(PA) {$float} has " , (preg_match('~\.\K0+~', $float, $match) ? strlen($match[0]) : 0) , " zero(s)\n";
}
输出:
(Math) 25.000000000022 has 10 zero(s)
Barmar 25.000000000022 has 10 zero(s)
(PMA) 25.000000000022 has 10 zero(s)
(PA) 25.000000000022 has 10 zero(s)
(Math) 6.2E-6 has 5 zero(s)
Barmar 6.2E-6 has 0 zero(s)
(PMA) 6.2E-6 has 0 zero(s)
(PA) 6.2E-6 has 0 zero(s)
(Math) 0.02032 has 1 zero(s)
Barmar 0.02032 has 1 zero(s)
(PMA) 0.02032 has 1 zero(s)
(PA) 0.02032 has 1 zero(s)
(Math) 0.505 has 0 zero(s)
Barmar 0.505 has 0 zero(s)
(PMA) 0.505 has 0 zero(s)
(PA) 0.505 has 0 zero(s)
(Math) 0 has Rendered as 0 zero(s)
Barmar 0 has 0 zero(s)
(PMA) 0 has 0 zero(s)
(PA) 0 has 0 zero(s)
(Math) 0.000507 has 3 zero(s)
Barmar 0.000507 has 3 zero(s)
(PMA) 0.000507 has 3 zero(s)
(PA) 0.000507 has 3 zero(s)
(Math) -0.002009 has 2 zero(s)
Barmar -0.002009 has 2 zero(s)
(PMA) -0.002009 has 2 zero(s)
(PA) -0.002009 has 2 zero(s)
(Math) 1000 has Rendered as 0 zero(s)
Barmar 1000 has 3 zero(s)
(PMA) 1000 has 0 zero(s)
(PA) 1000 has 0 zero(s)
(Math) 0 has Rendered as 0 zero(s)
Barmar 0 has 0 zero(s)
(PMA) 0 has 0 zero(s)
(PA) 0 has 0 zero(s)
(Math) -3.9990233346998E-13 has 12 zero(s)
Barmar -3.9990233346998E-13 has 0 zero(s)
(PMA) -3.9990233346998E-13 has 0 zero(s)
(PA) -3.9990233346998E-13 has 0 zero(s)
(Math) 981 has Rendered as 0 zero(s)
Barmar 981 has 0 zero(s)
(PMA) 981 has 0 zero(s)
(PA) 981 has 0 zero(s)
答案 2 :(得分:0)
匹配尾数中的第一个连续零:
$number = 123.0000000240003;
preg_match("/^(0+)/", explode('.', $number)[1], $matches);
echo strlen($matches[0]); // echoes 7