PHPの小数点以下2桁に切り捨てる必要があります。
49.955
になる...
49.95
number_formatを試しましたが、これは値を49.96に丸めるだけです。 substrを使用することはできません。これは、数値が小さい場合があるためです(7.950など)。これまでのところ、これに対する答えを見つけることができませんでした。
助けていただければ幸いです。
これは機能します:floor($number * 100) / 100
文字列関数を使用せずにトリックを実行するNice関数を次に示します。
<?php
function floorp($val, $precision)
{
$mult = pow(10, $precision); // Can be cached in lookup table
return floor($val * $mult) / $mult;
}
print floorp(49.955, 2);
?>
他のオプションは、丸める前に分数を減算することです:
function floorp($val, $precision)
{
$half = 0.5 / pow(10, $precision); // Can be cached in a lookup table
return round($val - $half, $precision);
}
残念ながら、以前の回答(受け入れられたものを含む)は、可能なすべての入力に対して機能しません。
1)sprintf('%1.'.$precision.'f', $val)
2の精度で失敗します。14.239は14.23を返します(ただし、この場合は14.24を返します)。
2)floatval(substr($val, 0, strpos($val, '.') + $precision + 1))
精度0で失敗します。14は14を返します(ただし、この場合は1を返します)
3)substr($val, 0, strrpos($val, '.', 0) + (1 + $precision))
精度0で失敗します:-1は-1を返します(ただし、この場合は '-'を返します)
4)floor($val * pow(10, $precision)) / pow(10, $precision)
私はこれを広範囲に使用しましたが、最近、その欠陥を発見しました。一部の値でも失敗します。 2の精度で:2.05は2.05を返します(ただし、この場合は2.04を返します!!)
これまでのところ、すべてのテストに合格する唯一の方法は、残念ながら文字列操作を使用することです。 rationalbossに基づく私のソリューションは、次のとおりです。
function floorDec($val, $precision = 2) {
if ($precision < 0) { $precision = 0; }
$numPointPosition = intval(strpos($val, '.'));
if ($numPointPosition === 0) { //$val is an integer
return $val;
}
return floatval(substr($val, 0, $numPointPosition + $precision + 1));
}
この関数は、正と負の数、および必要な精度で機能します。
入力を100倍し、floor()してから、結果を100で除算します。
round()
関数を試してください
このような:round($num, 2, PHP_ROUND_HALF_DOWN);
function roundDown($decimal, $precision)
{
$sign = $decimal > 0 ? 1 : -1;
$base = pow(10, $precision);
return floor(abs($decimal) * $base) / $base * $sign;
}
// Examples
roundDown(49.955, 2); // output: 49.95
roundDown(-3.14159, 4); // output: -3.1415
roundDown(1000.000000019, 8); // output: 1000.00000001
この関数は、任意の精度の正および負の小数で動作します。
function floorToPrecision($val, $precision = 2) {
return floor(round($val * pow(10, $precision), $precision)) / pow(10, $precision);
}
Bcdiv PHP関数。
bcdiv(49.955, 1, 2)
これを達成するための非常に簡単な方法があると思います:
$rounded = bcdiv($val, 1, $precision);
実施例 です。 BCMathをインストールする必要がありますが、通常はPHPインストール。:) ドキュメントはこちら にバンドルされていると思います。
次を使用できます。
$num = 49.9555;
echo substr($num, 0, strpos($num, '.') + 3);
最後の部分が5以下の場合にのみ小数を切り捨てる場合、最良の解決策は以下を使用することです。
round(4.955,2,PHP_ROUND_HALF_DOWN);
ここで、常に小数を切り捨てて、小数の量を制御したい場合、最善の解決策は次のとおりです。
round(floor(4.957*100)/100,2)
また、「100」の数値は「2」の10進数に合わせてスケーリングする必要があることも考慮してください。例えば。小数点以下4桁が必要な場合は、10000で乗算し、10000で除算する必要があります。そのため、そのポイントを超えると数字が失われます。
すべての正または負の数、整数または小数で動作する正規表現を使用した代替ソリューション:
if (preg_match('/^-?(\d+\.?\d{1,2})\d*$/', $originalValue, $matches)){
$roundedValue = $matches[1];
} else {
throw new \Exception('Cannot round down properly '.$originalValue.' to two decimal places');
}
@huysentruitwと@Alexの回答に基づいて、私はトリックを行う必要がある次の関数を思い付きました。
アレックスの答えで与えられたすべてのテストに合格し(これが不可能な理由として)、huysentruitwの答えに基づいて構築されます。
function trim_number($number, $decimalPlaces) {
$delta = (0 <=> $number) * (0.5 / pow(10, $decimalPlaces));
$result = round($number + $delta, $decimalPlaces);
return $result ?: 0; // get rid of negative zero
}
重要なのは、元の番号記号に基づいてデルタを加算または減算し、負の数のトリミングもサポートすることです。最後のことは、負のゼロ(-0)を取り除くことです。これは望ましくない動作になる可能性があるためです。
編集:bcdivは行く方法のようです。
// round afterwards to cast 0.00 to 0
// set $divider to 1 when no division is required
round(bcdiv($number, $divider, $decimalPlaces), $decimalPlaces);