Reputation: 8773
I have this number:
$double = '21.188624';
After using number_format($double, 2, ',', ' ')
I get:
21,19
But what I want is:
21,18
Any ideea how can I make this work?
Thank you.
Upvotes: 40
Views: 87427
Reputation: 1259
Modern PHP has a built-in NumberFormatter
class that supports various types of rounding. In your case you need ROUND_DOWN
mode
You can create your own formatter and set the desired rounding mode for it:
$fmt = new NumberFormatter('ru_RU', NumberFormatter::DECIMAL);
$fmt->setAttribute(NumberFormatter::FRACTION_DIGITS, 2);
$fmt->setAttribute(NumberFormatter::ROUNDING_MODE, NumberFormatter::ROUND_DOWN);
echo $fmt->format(21.188624); // 21,18
Upvotes: 0
Reputation: 1
thanks for your help Dima!!! My function
private function number_format(float $num, int $decimals = 0, ?string $decimal_separator = ',', ?string $thousands_separator = '.'){
/**
* Formatea un numero como number_format sin redondear hacia arriba, trunca el resultado
* @access private
* @param string num - Numero de va a ser formateado
* @param int decimals - Posiciones Decimales
* @param string|null $decimal_separator — [opcional]
* @param string|null $thousands_separator — [opcional]
* @return string — Version de numero formateado.
*/
$negation = ($num < 0) ? (-1) : 1;
$coefficient = 10 ** $decimals;
$number = $negation * floor((string)(abs($num) * $coefficient)) / $coefficient;
return number_format($number, $decimals, $decimal_separator, $thousands_separator);
}
for use it
echo $this->number_format(24996.46783, 3, ',', '.'); //24.996,467
Upvotes: 0
Reputation: 1
$number = 2.278;
echo new_number_format($number,1);
//result: 2.2
function new_number_format($number,$decimal)
{
//explode the number with the delimiter of dot(.) and get the whole number in index 0 and the decimal in index 1
$num = explode('.',$number);
//if the decimal is equal to zero
//take note that we can't split the zero value only and it will return Undefined offset if we split the zero only
//for example: rating_format(2.0,1); the result will be 2. the zero is gone because of the Undefined offset
//the solution of this problem is this condition below
if($num[1] == 0)
{
$final_decimal = '';
$i=0;
//loop the decimal so that we can display depend on how many decimal that you want to display
while($i<$decimal){
$final_decimal .= 0;
$i++;
}
}
//if the decimal is not zero
else
{
$dec = str_split($num[1]); //split the decimal and get the value using the array index
$i=0;
$final_decimal = '';
//loop the decimal so that we can display depend on how many decimal that you want to display
while($i<$decimal){
$final_decimal .= $dec[$i];
$i++;
}
}
$new_number= $num[0].'.'.$final_decimal;//combine the result with final decimal
return $new_number; //return the final output
}
Upvotes: 0
Reputation: 72
In case you need 2 fixed decimal places, you can try this!
@Dima's solution is working for me, but it prints "19.90" as "19.9" so I made some changes as follows:
<?php
function numberPrecision($number, $decimals = 0)
{
$negation = ($number < 0) ? (-1) : 1;
$coefficient = 10 ** $decimals;
$result = $negation * floor((string)(abs($number) * $coefficient)) / $coefficient;
$arr = explode(".", $result);
$num = $arr[0];
if(empty($arr[1]))
$num .= ".00";
else if(strlen($arr[1]) == 1)
$num .= "." . $arr[1] . "0";
else
$num .= ".". $arr[1];
return $num;
}
echo numberPrecision(19.90,2); // 19.90
So, what I did is, I just break the result into two parts with explode function. and convert the result into a string with concatenation!
Upvotes: 1
Reputation: 319
Function (only precision):
function numberPrecision($number, $decimals = 0)
{
$negation = ($number < 0) ? (-1) : 1;
$coefficient = 10 ** $decimals;
return $negation * floor((string)(abs($number) * $coefficient)) / $coefficient;
}
Examples:
numberPrecision(2557.9999, 2); // returns 2557.99
numberPrecision(2557.9999, 10); // returns 2557.9999
numberPrecision(2557.9999, 0); // returns 2557
numberPrecision(2557.9999, -2); // returns 2500
numberPrecision(2557.9999, -10); // returns 0
numberPrecision(-2557.9999, 2); // returns -2557.99
numberPrecision(-2557.9999, 10); // returns -2557.9999
numberPrecision(-2557.9999, 0); // returns -2557
numberPrecision(-2557.9999, -2); // returns -2500
numberPrecision(-2557.9999, -10); // returns 0
Function (full functionality):
function numberFormat($number, $decimals = 0, $decPoint = '.' , $thousandsSep = ',')
{
$negation = ($number < 0) ? (-1) : 1;
$coefficient = 10 ** $decimals;
$number = $negation * floor((string)(abs($number) * $coefficient)) / $coefficient;
return number_format($number, $decimals, $decPoint, $thousandsSep);
}
Examples:
numberFormat(2557.9999, 2, ',', ' '); // returns 2 557,99
numberFormat(2557.9999, 10, ',', ' '); // returns 2 557,9999000000
numberFormat(2557.9999, 0, ',', ' '); // returns 2 557
numberFormat(2557.9999, -2, ',', ' '); // returns 2 500
numberFormat(2557.9999, -10, ',', ' '); // returns 0
numberFormat(-2557.9999, 2, ',', ' '); // returns -2 557,99
numberFormat(-2557.9999, 10, ',', ' '); // returns -2 557,9999000000
numberFormat(-2557.9999, 0, ',', ' '); // returns -2 557
numberFormat(-2557.9999, -2, ',', ' '); // returns -2 500
numberFormat(-2557.9999, -10, ',', ' '); // returns 0
Upvotes: 17
Reputation: 123
Javascript Version
function numberFormat($number, $decimals = 0, $decPoint = '.' , $thousandsSep = ',')
{
return number_format((Math.floor($number * 100) / 100).toFixed($decimals), $decimals, $decPoint, $thousandsSep );
}
// https://locutus.io/php/strings/number_format/
function number_format(number, decimals, decPoint, thousandsSep) {
if(decimals === 'undefined') decimals = 2;
number = (number + '').replace(/[^0-9+\-Ee.]/g, '')
const n = !isFinite(+number) ? 0 : +number
const prec = !isFinite(+decimals) ? 0 : Math.abs(decimals)
const sep = (typeof thousandsSep === 'undefined') ? ',' : thousandsSep
const dec = (typeof decPoint === 'undefined') ? '.' : decPoint
let s = ''
const toFixedFix = function (n, prec) {
if (('' + n).indexOf('e') === -1) {
return +(Math.round(n + 'e+' + prec) + 'e-' + prec)
} else {
const arr = ('' + n).split('e')
let sig = ''
if (+arr[1] + prec > 0) {
sig = '+'
}
return (+(Math.round(+arr[0] + 'e' + sig + (+arr[1] + prec)) + 'e-' + prec)).toFixed(prec)
}
}
// @todo: for IE parseFloat(0.55).toFixed(0) = 0;
s = (prec ? toFixedFix(n, prec).toString() : '' + Math.round(n)).split('.')
if (s[0].length > 3) {
s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep)
}
if ((s[1] || '').length < prec) {
s[1] = s[1] || ''
s[1] += new Array(prec - s[1].length + 1).join('0')
}
return s.join(dec)
}
Upvotes: 0
Reputation: 1283
I know that this an old question, but it still actual :) .
How about this function?
function numberFormatPrecision($number, $precision = 2, $separator = '.')
{
$numberParts = explode($separator, $number);
$response = $numberParts[0];
if (count($numberParts)>1 && $precision > 0) {
$response .= $separator;
$response .= substr($numberParts[1], 0, $precision);
}
return $response;
}
Usage:
// numbers test
numberFormatPrecision(19, 2, '.'); // expected 19 return 19
numberFormatPrecision(19.1, 2, '.'); //expected 19.1 return 19.1
numberFormatPrecision(19.123456, 2, '.'); //expected 19.12 return 19.12
numberFormatPrecision(19.123456, 0, '.'); //expected 19 return 19
// negative numbers test
numberFormatPrecision(-19, 2, '.'); // expected -19 return -19
numberFormatPrecision(-19.1, 2, '.'); //expected -19.1 return -19.1
numberFormatPrecision(-19.123456, 2, '.'); //expected -19.12 return -19.12
numberFormatPrecision(-19.123456, 0, '.'); //expected -19 return -19
// precision test
numberFormatPrecision(-19.123456, 4, '.'); //expected -19.1234 return -19.1234
// separator test
numberFormatPrecision('-19,123456', 3, ','); //expected -19,123 return -19,123 -- comma separator
Upvotes: 21
Reputation: 12222
I use this function:
function cutNum($num, $precision = 2) {
return floor($num) . substr(str_replace(floor($num), '', $num), 0, $precision + 1);
}
Usage examples:
cutNum(5) //returns 5
cutNum(5.6789) //returns 5.67 (default precision is two decimals)
cutNum(5.6789, 3) //returns 5.678
cutNum(5.6789, 10) //returns 5.6789
cutNum(5.6789, 0) //returns 5. (!don't use with zero as second argument: use floor instead!)
Explanation: here you have the same function, just more verbose to help understanding its behaviour:
function cutNum($num, $precision = 2) {
$integerPart = floor($num);
$decimalPart = str_replace($integerPart, '', $num);
$trimmedDecimal = substr($decimalPart, 0, $precision + 1);
return $integerPart . $trimmedDecimal;
}
Upvotes: 5
Reputation: 99
$double = '21.188624';
$teX = explode('.', $double);
if(isset($teX[1])){
$de = substr($teX[1], 0, 2);
$final = $teX[0].'.'.$de;
$final = (float) $final;
}else{
$final = $double;
}
final will be 21.18
Upvotes: 1
Reputation: 122
The faster way as exploding(building arrays) is to do it with string commands like this:
$number = ABC.EDFG;
$precision = substr($number, strpos($number, '.'), 3); // 3 because . plus 2 precision
$new_number = substr($number, 0, strpos($number, '.')).$precision;
The result ist ABC.ED in this case because of 2 precision If you want more precision just change the 3 to 4 or X to have X-1 precision
Cheers
Upvotes: 0
Reputation: 1966
In Case you have small float
values you can use number_format
function this way.
$number = 21.23;
echo number_format($number, 2, '.', ',') ); // 21.23
In case you have you have long decimal number then also it will format number this way
$number = 201541.23;
echo number_format($number, 2, '.', ',') ); // 201,541.23
Upvotes: -1
Reputation: 11579
Use the PHP native function bcdiv.
function numberFormat($number, $decimals = 2, $sep = ".", $k = ","){
$number = bcdiv($number, 1, $decimals); // Truncate decimals without rounding
return number_format($number, $decimals, $sep, $k); // Format the number
}
See this answer for more details.
Upvotes: 4
Reputation: 300
**Number without round**
$double = '21.188624';
echo intval($double).'.'.substr(end(explode('.',$double)),0,2);
**Output** 21.18
Upvotes: 2
Reputation: 1554
In case you don't care for what comes behind the decimal point, you can cast the float
as an int
to avoid rounding:
$float = 2.8;
echo (int) $float; // outputs '2'
Upvotes: 0
Reputation: 675
$finalCommishParts = explode('.',$commission);
$commisshSuffix = (isset($finalCommishParts[1])?substr($finalCommishParts[1],0,2):'00');
$finalCommish = $finalCommishParts[0].'.'.$commisshSuffix;
Upvotes: 0
Reputation: 730
public function numberFormatPrecision( $number, $separator = '.', $format = 2 ){
$response = '';
$brokenNumber = explode( $separator, $number );
$response = $brokenNumber[0] . $separator;
$brokenBackNumber = str_split($brokenNumber[1]);
if( $format < count($brokenBackNumber) ){
for( $i = 1; $i <= $format; $i++ )
$response .= $brokenBackNumber[$i];
}
return $response;
}
Upvotes: 0
Reputation: 12437
use this function:
function number_format_unlimited_precision($number,$decimal = '.')
{
$broken_number = explode($decimal,$number);
return number_format($broken_number[0]).$decimal.$broken_number[1]);
}
Upvotes: -1
Reputation: 70470
number_format
will always do that, your only solution is to feed it something different:
$number = intval(($number*100))/100;
Or:
$number = floor(($number*100))/100;
Upvotes: 39