PHP - 查找十进制数中的零个数

Posted

技术标签:

【中文标题】PHP - 查找十进制数中的零个数【英文标题】:PHP - Find the number of zeros in a decimal number 【发布时间】:2013-11-05 23:47:15 【问题描述】:

假设我们有 0.00045。我想找到一种方法来计算小数点后“重要”零的数量(在本例中为 3)。我一直在尝试实现strpossubstr,但我卡住了。

其他前任……

3.006405:应该返回“2” 0.0000062:应该返回“5” 9.0100000008:应该返回“1”

有什么想法吗?

【问题讨论】:

尝试strspn() 找出零序列的长度。 好吧,如此重要的 0,可能会涉及使用循环。我会尝试将小数转换为字符串,通过循环遍历它并使用一堆 if 语句来检查各种有效数字规则。如果所有 if 语句都有效,只需有一个计数器并递增它。 是在小数点后面吗?它们必须是连续的吗? 【参考方案1】:
strspn($num, "0", strpos($num, ".")+1)

strspn 查找零序列的长度。 strpos 找到小数点的位置,我们从过去的 1 位开始。

但是,这不适用于0.0000062,因为它在转换为字符串时会转换为科学记数法:6.200000e-6。当数字以e-<exponent> 结尾时,零的数量为<exponent>-1。您可以使用正则表达式进行检查。

【讨论】:

【参考方案2】:

我决定在处理这项任务时研究一些不同的可能性。

我必须说,Barmar 的解决方案易于阅读,非常适合不受科学记数法影响的浮点数。

作为一个思想实验,我决定制作几个正则表达式来完成同样的工作。 (*即使您将整数值传递给正则表达式方法,它们仍然有效。)

    对于 preg_match_all(),我使用“继续”元字符 (\G) 来匹配第一个 .0,然后是紧随其后的零个或多个 0。 使用preg_match(),我可以更简单地匹配点,然后用\K“忘记它”(重新开始全字符串匹配),然后从该位置匹配1个或多个零。不幸的是,这需要额外调用str_len()。我通常只支持preg_ 调用,因为它导致的函数调用比非正则表达式方法更少。

受https://codereview.stackexchange.com/q/219601/141885 的启发,我想编写一个函数来仅使用算术(猜测和检查)计算小数点后的零。 虽然它不像其他的那样受到科学记数法的影响,但它并不完美,并且在不同的操作系统/版本/环境/yatta-yatta 上对浮点数/整数有限制(我不假装知道所有细节,但我知道存在差异)。继续使用您的项目数据尝试其中的一些方法,并随时让 cmets 了解哪些有效哪些无效。 ...如果你知道为什么我邀请你教育我:)

最后,*** (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)

【讨论】:

【参考方案3】:

匹配尾数中第一个连续的零:

$number = 123.0000000240003;

preg_match("/^(0+)/", explode('.', $number)[1], $matches);

echo strlen($matches[0]); // echoes 7

【讨论】:

以上是关于PHP - 查找十进制数中的零个数的主要内容,如果未能解决你的问题,请参考以下文章

统计二进制数中的1的个数(0277)

统计二进制数中的1的个数

求二进制数中1的个数

c语言中如何提取二进制数中的某一位?

C++ 位运算计算二进制数中的1的个数

求二进制数中1的个数——引发的问题