如何在php中将数字舍入到最接近的有效数字

5
有没有一种简便的方法在php中向下取整到最接近的有效数字?
因此:
0->0
9->9
10->10
17->10
77->70
114->100
745->700
1200->1000

?

8个回答

8
$numbers = array(1, 9, 14, 53, 112, 725, 1001, 1200);
foreach($numbers as $number) {
    printf('%d => %d'
            , $number
            , $number - $number % pow(10, floor(log10($number)))
            );
    echo "\n";
}

不幸的是,当$number为0时,这种方法会彻底失败,但对于正整数它确实能够产生预期的结果。并且这是一种仅涉及数学的解决方案。


4
这里有一个纯数学的解决方案。如果您需要四舍五入而不仅仅是向下取整,那么这也是一种更灵活的解决方案。并且它适用于0 :)
if($num === 0) return 0;
$digits = (int)(log10($num));
$num = (pow(10, $digits)) * floor($num/(pow(10, $digits)));

你可以将floor替换为roundceil。实际上,如果你想要四舍五入到最近的整数,你甚至可以更简单地简化第三行代码。
$num = round($num, -$digits);

在处理零时,除以零警告之外,它是有效的。 - Kzqai
我以为我避免了除以0,但我忘记了0的对数。 - andrewtweber

3
如果您想要一种数学解决方案,请尝试这个:
function floorToFirst($int) {
    if (0 === $int) return 0;

    $nearest = pow(10, floor(log($int, 10)));
    return floor($int / $nearest) * $nearest;
}

1

我知道这是一个旧帖子,但当我寻找灵感来解决这个问题时,我阅读了它。以下是我想出的解决方案:

class Math
{
    public static function round($number, $numberOfSigFigs = 1)
    {
        // If the number is 0 return 0
        if ($number == 0) {
            return 0;
        }

        // Deal with negative numbers
        if ($number < 0) {
            $number = -$number;
            return -Math::sigFigRound($number, $numberOfSigFigs);
        }

        return Math::sigFigRound($number, $numberOfSigFigs);
    }

    private static function sigFigRound($number, $numberOfSigFigs)
    {
        // Log the number passed
        $log = log10($number);

        // Round $log down to determine the integer part of the log
        $logIntegerPart = floor($log);

        // Subtract the integer part from the log itself to determine the fractional part of the log
        $logFractionalPart = $log - $logIntegerPart;

        // Calculate the value of 10 raised to the power of $logFractionalPart
        $value = pow(10, $logFractionalPart);

        // Round $value to specified number of significant figures
        $value = round($value, $numberOfSigFigs - 1);

        // Return the correct value
        return $value * pow(10, $logIntegerPart); 
    }
}

1
"

这完全不需要数学计算,可以使用字符串长度来实现...也许有更优雅的处理方法,但你可以用这种方式实现它

"
function significant($number){
    $digits = count($number);
    if($digits >= 2){
        $newNumber = substr($number,0,1);
        $digits--;
        for($i = 0; $i < $digits; $i++){
            $newNumber = $newNumber . "0";
        }
    }
    return $newNumber;
}

1

一种基于数学的替代方案:

$mod = pow(10, intval(round(log10($value) - 0.5))); 
$answer = ((int)($value / $mod)) * $mod;

1

类似这样:

$str = (string)$value;
echo (int)($str[0] . str_repeat('0', strlen($str) - 1));

哎呀,真是棘手。我还以为我得学点数学呢。 - Kzqai
1
使用字符串作为基本数学运算的替代品从来都不是一个正确的想法。 - BlueRaja - Danny Pflughoeft

0
虽然这里的函数可以使用,但是我需要对非常小的数字(比较低价值的加密货币与比特币)进行有效数字的处理。 在PHP中将数字格式化为N个有效数字的答案可以使用,但是PHP会以科学计数法显示非常小的数字,这使得一些人难以阅读。

enter image description here

我尝试使用number_format,但它需要小数点后特定数量的数字,这破坏了数字的“重要”部分(如果输入了一组数字),有时会返回0(对于小于设置数字的数字)。

解决方案是修改函数以识别非常小的数字,然后在它们上面使用number_format-将科学计数法数字的数量作为number_format的数字:

function roundRate($rate, $digits)
{
    $mod = pow(10, intval(round(log10($rate))));
    $mod = $mod / pow(10, $digits);
    $answer = ((int)($rate / $mod)) * $mod;
    $small = strstr($answer,"-");
    if($small)
    {
        $answer = number_format($answer,str_replace("-","",$small));
    }
    return $answer;
}

这个函数保留了有效数字,并以易于阅读的格式呈现数字,适合所有人使用。(我知道,对于科学家来说可能不是最好的选择,也不是最一致长度的“漂亮”数字,但总体上它是我们所需的最佳解决方案。)

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接