有没有什么巧妙的方法可以四舍五入到 php 中最接近的有效数字?
所以:
0->0
9->9
10->10
17->10
77->70
114->100
745->700
1200->1000
?
有没有什么巧妙的方法可以四舍五入到 php 中最接近的有效数字?
所以:
0->0
9->9
10->10
17->10
77->70
114->100
745->700
1200->1000
?
$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 时,这会严重失败,但它确实会产生正整数的预期结果。这是一个仅限数学的解决方案。
这是一个纯数学解决方案。如果您想向上或向下舍入,而不仅仅是向下舍入,这也是一个更灵活的解决方案。它适用于 0 :)
if($num === 0) return 0;
$digits = (int)(log10($num));
$num = (pow(10, $digits)) * floor($num/(pow(10, $digits)));
您可以替换floor
为round
或ceil
。实际上,如果你想四舍五入,你可以进一步简化第三行。
$num = round($num, -$digits);
如果您确实想要一个数学解决方案,请尝试以下操作:
function floorToFirst($int) {
if (0 === $int) return 0;
$nearest = pow(10, floor(log($int, 10)));
return floor($int / $nearest) * $nearest;
}
像这样的东西:
$str = (string)$value;
echo (int)($str[0] . str_repeat('0', strlen($str) - 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;
}
基于数学的替代方案:
$mod = pow(10, intval(round(log10($value) - 0.5)));
$answer = ((int)($value / $mod)) * $mod;
我知道这是一个旧线程,但我在寻找如何解决这个问题的灵感时阅读了它。这是我想出的:
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);
}
}
虽然这里的功能有效,但我需要非常小的数字的有效数字(将低价值加密货币与比特币进行比较)。
在 PHP 中将数字格式化为 N 个有效数字的答案在某种程度上起作用了,尽管 PHP 以科学计数法显示非常小的数字,这使某些人难以阅读。
我尝试使用 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;
}
此功能保留有效数字,并以易于阅读的格式为每个人提供数字。(我知道,对于科学界人士来说,这不是最好的,甚至不是最一致的长度“漂亮”的数字,但它总体上是我们需要的最佳解决方案。)