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
ます。実際、最も近い値に丸めたい場合は、3行目をさらに単純化できます。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;
}
この関数は、有効数字を保持するだけでなく、すべての人に読みやすい形式で数値を表示します。(私は知っています、それは科学者にとっても、最も一貫した長さの「きれいな」見た目の数字でさえも最善ではありませんが、私たちが必要としたものにとって全体的に最良の解決策です。)