I am looking for a solution for a smart number formatting in PHP.
For example we have 2 numbers below and we need 4 digits after decimal:
1.12345678
0.00002345678
Using normal number formatting, here are the results:
1.1234 // Looking good
0.0000 // No good
Can we make it keep going until there are 4 non-zero digits? If it can return 0.00002345, perfect!!!
Many thanks!!!
Might be overkill and the pattern could be optimized, but for fun; get optional 0s AND 4 NOT 0s after the .:
preg_match('/\d+\.([0]+)?[^0]{4}/', $num, $match);
echo $match[0];
To round it we can get 5 digits after the 0s and then format it to the length of that -1 (which will round):
preg_match('/\d+\.([0]+?[^0]{5})/', $num, $match);
echo number_format($match[0], strlen($match[1])-1);
For $num = '1234.000023456777'; the result will be 1,234.00002346 and the $matches will contain:
Array
(
[0] => 1234.000023456
[1] => 000023456
)
So this is the code I made to slove this:
$num = 0.00002345678;
$num_as_string = number_format($num,PHP_FLOAT_DIG,'.','');
$zeros = strspn($num_as_string, "0", strpos($num_as_string, ".")+1);
echo number_format($num, (4+$zeros), '.', '');
It converts the float number to a string, checks how many zeros exist after the decimal point and then does a number format with the extra zeros accounted for.
Note that it may break if your float is too big, you can change PHP_FLOAT_DIG to a number larger that may fix that.
Related
What I am trying to do is :
0.000000023455676554434 -> 0.0000002345
0.00000000000000000000002656565-> 0.00000000000000000000002656
0.012345 -> 0.01234
Code till now :
bcdiv(rtrim(sprintf('%.20f', $decimal), '0'),1,13);
The current code removes scientific notation, and trims any zeros towards the end if any, and cuts the decimals after 13 decimal points. but if the decimal is something like 0.023123123235435346 it would still show 13 decimal points while I am looking to get only 0.02312.
Any help wold be highly appreciated.
You can use base 10 log to get the number of zeros between the point and the first digit. This would do what you want:
$decimal = "0.00000000000000000000002656565";
echo bcdiv($decimal, 1, -1*floor(log($decimal, 10))-1+4);
Output: 0.00000000000000000000002656
I think preg_replace is also very easy to do. The value should be available as strings and not as float.
$trimValue = preg_replace('~(\d*\.0*[1-9]{4}).*~','$1',$value);
If you want 4 numbers after first non-zero number use this:
$trimValue = preg_replace('~(\d*\.0*[1-9]\d{3}).*~','$1',$value);
A complete test (First variant):
$data = [
'0.000000023455676554434', // -> 0.0000002345
'0.00000000000000000000002656565', //-> 0.00000000000000000000002656
'0.012345', // -> 0.01234
'0.023123123235435346', //0.02312
'0.00565',
];
$trimValues = [];
foreach($data as $value){
$trimValues[] = preg_replace('~(\d*\.0*[1-9]{4}).*~','$1',$value);
}
echo '<pre>';
var_export($trimValues);
Output:
array (
0 => '0.00000002345',
1 => '0.00000000000000000000002656',
2 => '0.01234',
3 => '0.02312',
4 => '0.00565',
)
Is there a way with number_format() to leave out decimal places if the number is not a float/decimal?
For example, I would like the following input/output combos:
50.8 => 50.8
50.23 => 50.23
50.0 => 50
50.00 => 50
50 => 50
Is there a way to do this with just a standard number_format()?
You can add 0 to the formatted string. It will remove trailing zeros.
echo number_format(3.0, 1, ".", "") + 0; // 3
A Better Solution: The above solution fails to work for specific locales. So in that case, you can just type cast the number to float data type. Note: You might loose precision after type casting to float, bigger the number, more the chances of truncating the number.
echo (float) 3.0; // 3
Ultimate Solution: The only safe way is to use regex:
echo preg_replace("/\.?0+$/", "", 3.0); // 3
echo preg_replace("/\d+\.?\d*(\.?0+)/", "", 3.0); // 3
Snippet 1 DEMO
Snippet 2 DEMO
Snippet 3 DEMO
If you want to use whitespace here is better solution
function real_num ($num, $float)
{
if (!is_numeric($num) OR is_nan($num) ) return 0;
$r = number_format($num, $float, '.', ' ');
if (false !== strpos($r, '.'))
$r = rtrim(rtrim($r, '0'), '.');
return $r;
}
Use:
$a = 50.00;
$a = round($a, 2);
Even though the number has 2 zeros trailing it, if you round it, it won't show the decimal places, unless they have some kind of value.
So 50.00 rounded using 2 places will be 50, BUT 50.23 will be 50.23.
Unless you specify at which point to round up or down, it won't change your decimal values. So just use default round()
Number format adds the commas I want but removes the decimals.
echo number_format("1000000.25");
This returns 1,000,000
I want it to return 1,000,000.25
I need both the commas and the decimals, without any number rounding. All my values are decimals. They vary in length.
Do I have to use something other than number format?
In case what you meant by they vary in length is related to the decimal part, take a look at this code:
function getLen($var){
$tmp = explode('.', $var);
if(count($tmp)>1){
return strlen($tmp[1]);
}
}
$var = '1000000.255555'; // '1000000.25'; // '1000000';
echo number_format($var, getLen($var));
Some tests
Output for 1000000.255555:
1,000,000.255555
Output for 1000000.25:
1,000,000.25
Output for 1000000:
1,000,000
It counts how many chars there are after the . and uses that as argument in the number_format function;
Otherwise just use a constant number instead of the function call.
And some reference...
From the manual -> number_format():
string number_format ( float $number [, int $decimals = 0 ] )
And you can see in the description that
number
The number being formatted.
decimals
Sets the number of decimal points.
And a bit more:
[...]If two parameters are given, number will be formatted with decimals
decimals with a dot (".") in front, and a comma (",") between every
group of thousands.
$number = '1000000.25';
echo number_format($number, strlen(substr(strrchr($number, "."), 1)));
Explanation:
Number Format takes a second parameter which specifies the number of decimal places required as pointed out in the docs. This Stack overflow answer tells you how to get the number of decimal places of your provided string
The docs for number_format() indicate the second parameter is used to specify decimal:
echo number_format('1000000.25', 2);
Ref: http://php.net/manual/en/function.number-format.php
How to make number like 3.0000000054978E+38 to 3.00 in PHP?
Many thanks!
You cannot use round to solve this since it is a number in scientific notation. You can, however, use substr:
$i = 3.0000000054978E+38;
$i = substr($i, 0, 2); // $i is now the string 3.00
echo( number_format($i+1,2) ); // Will output 4.00
In case you are looking for the small fraction of your number being outputted in a formatted fashion:
$number = 3.0000000054978E+38;
printf('%.2f', $number / 1E+38); # 3.00
You can just use round, as in round($floating_number, 2).
sprintf() always gives you the specified number of decimal points, if you require.
sprintf('%0.2f', 3.0000000);
Would display 3.00, if you echo it.
How can I separate a number and get the first two digits in PHP?
For example: 1345 -> I want this output=> 13 or 1542 I want 15.
one possibility would be to use substr:
echo substr($mynumber, 0, 2);
EDIT:
please not that, like hakre said, this will break for negative numbers or small numbers with decimal places. his solution is the better one, as he's doing some checks to avoid this.
First of all you need to normalize your number, because not all numbers in PHP consist of digits only. You might be looking for an integer number:
$number = (int) $number;
Problems you can run in here is the range of integer numbers in PHP or rounding issues, see Integers Docs, INF comes to mind as well.
As the number now is an integer, you can use it in string context and extract the first two characters which will be the first two digits if the number is not negative. If the number is negative, the sign needs to be preserved:
$twoDigits = substr($number, 0, $number < 0 ? 3 : 2);
See the Demo.
Shouldn't be too hard? A simple substring should do the trick (you can treat numbers as strings in a loosely typed language like PHP).
See the PHP manual page for the substr() function.
Something like this:
$output = substr($input, 0, 2); //get first two characters (digits)
You can get the string value of your number then get the part you want using
substr.
this should do what you want
$length = 2;
$newstr = substr($string, $lenght);
With strong type-hinting in new version of PHP (> PHP 7.3) you can't use substr on a function if you have integer or float. Yes, you can cast as string but it's not a good solution.
You can divide by some ten factor and recast to int.
$number = 1345;
$mynumber = (int)($number/100);
echo $mynumber;
Display: 13
If you don't want to use substr you can divide your number by 10 until it has 2 digits:
<?php
function foo($i) {
$i = abs((int)$i);
while ($i > 99)
$i = $i / 10;
return $i;
}
will give you first two digits