I hold decimals in a database using DECIMAL(10,5)
I would like to format these numbers according to a few rules:
A zero decimal should display as 0
Show a long decimal (no trailing zero's) with all of it's numbers
When possible, I would like to only show up to 2 decimal places (when there are trailing zeros)
Here are some examples:
The left side corresponds to how the number is stored in database.
The right number is how I would like to display the number in my application.
0.00000 => 0
0.51231 => 0.51231
0.12000 => 0.12
0.40000 => 0.40
0.67800 => 0.678
12.10000 => 12.10
This will work for you:
function format($x){
if(!(int)substr_replace($x, '', $dpos = strpos($x, '.'), 1))
return 0;
else
return str_pad((rtrim($x, '0')), $dpos + 3, '0');
}
Example
I would utilize the number_format function in php to actually do the formatting after you determine the amount of decimal places to the number has.
Source:
http://php.net/manual/en/function.number-format.php
Example Usage:
$number = 1234.56;
// english notation (default)
$english_format_number = number_format($number);
// 1,235
// French notation
$nombre_format_francais = number_format($number, 2, ',', ' ');
// 1 234,56
$number = 1234.5678;
// english notation without thousands separator
$english_format_number = number_format($number, 2, '.', '');
// 1234.57
Well here's one way (I haven't tested it yet so there may be minor errors):
$pattern = '/([0-9]+)\\.{0,1}([0-9]*?)0*$/';
$subject = 12.10000;
$matches = array();
$result = preg_match ($pattern, $subject, $matches);
$number = $matches[1];
if ($matches[2] != 0) {
$number .= '.'.$matches[2];
if ($matches[2] < 10) {
$number .= '0';
}
}
echo $number;
And here's another way (probably a little faster):
$x = 1.000;
$result = (int)$x;
$trimmed = rtrim($x, 0);
if ($trimmed[strlen($trimmed) - 1] != '.') {
if ($trimmed[strlen($trimmed) - 2] == '.') {
$result = $trimmed.'0';
} else {
$result = $trimmed;
}
}
echo $result;
I haven't used it myself, but theres the NumberFormatter class: http://php.net/manual/class.numberformatter.php as part of the Internationalization Functions for this stuff. Using that is a little more involved i think though.
I know this is an old question, but the following quick function I wrote for my own project might help someone looking for this.
function number_format_least_dp($number, $decimal_point = '.', $thousand_seperator = ','){
if (floatval($number) == (int)$number){
$number = number_format($number, 0, $decimal_point, $thousand_seperator);
} else {
$number = rtrim($number, '.0');
$number = number_format($number, strlen(substr(strrchr($number, '.'), 1)), $decimal_point, $thousand_seperator);
}
return $number;
}
Related
I am a php noob (very) and i got following code:
<?echo getPointsColor($row["fld_points"])?>
Currently the number 1234 in the database is shown as 1,234, but i would like to have it 1234 (without as thousand seperator).
I found:
$english_format_number = number_format($number, 0, '.', '');
This would make it 1234 instead of 1,234
BUT i don't know how to change my code (first code above) to make it work. Can someone post me how the correct codechange would like like?
Info, here is the the function:
function getPointsColor($points_to_color)
{
$myp = intval($points_to_color);
if($myp <= 0)
$myp = "<font color='#a71212\'>".number_format($myp,'\'')."</font>";
else
$myp = "<font color='#4ea712\'>".number_format($myp,'\'')."</font>";
return $myp;
}
You can do it like this:
$english_format_number = number_format($number, 2, '.', ',');
Reference
The third parameter sets the decimal separator, the fourth sets the thousands separator.
OK thanks to all!
I have edited the functions as following and it works:
function getPointsColor($points_to_color)
{
$myp = intval($points_to_color);
if($myp <= 0)
$myp = "<font color='#a71212\'>".number_format($myp, 0, '.', '')."</font>";
else
$myp = "<font color='#4ea712\'>".number_format($myp, 0, '.', '')."</font>";
return $myp;
}
I'm having some trouble getting the price to show correct on my website. Currently i have a row VerkoopPP40 which is a VARCHAR input. In this row there is a price e.g. 89,5 or just 9. When I try to get these values it does some unexpected things.
**** Update ****
I've just tried this code:
<?php
function formatNumber($number, $format=[], $oldDecimalSeparator=",.·'", $multiplier=1)
{
if ($format) {
$format += ['numOfDecimals' => 0, 'decimalSeparator' => '.', 'thousandSeparator' => '']; # Default format
# Find decimal separator
# The decimal separator is the one that is the last and does not occur more than once
if ($letters = str_replace(' ', '', $number)) { # Replace spaces
if ($letters = preg_replace('/^-/', '', $letters)) { # Remove minus
if ($letters = preg_replace('/[0-9]/', '', $letters)) { # Get all non digits
$lastletter = substr($letters, -1); # Returns last char
if (substr_count($letters, $lastletter) == 1) {
if (strpos($oldDecimalSeparator, $lastletter) !== false)
$oldDecimalSep = $lastletter;
else
return $number;
}
}
}
}
$number = preg_replace('/[^0-9-]/', '', $number); # Remove all non digits except 'minus'
if ($oldDecimalSep)
$number = str_replace($oldDecimalSep, '.', $number); # Format to float
if ($multiplier != 1)
$number = $number * $multiplier;
# Convert float to new format
$number = number_format($number,
$format['numOfDecimals'],
$format['decimalSeparator'],
$format['thousandSeparator']
);
}
return $number;
}
This returns: 9,00 and 895,00 so the comma is in a different place right now. It's something I guess... Anyone got an idea to move the comma and remove a 0.
**** End Update ****
And echo-ed it like this:
<td><p>vanaf " . formatNumber($number, [
'numOfDecimals' => 2,
'decimalSeparator' => ',',
'thousandSeparator' => ' '
], ',.') . " p.p. <small>Excl btw</small></p></td>
If I just echo the VerkoopPP40 row it returns: €89,5 or €9.
So I googled around some and found this:
$var = $row["VerkoopPP40"];
$var = ltrim($var, '0');
$foo = $var;
$prijzen = number_format($foo, 2, ',', '');
This turns the . into a ,. But also returns €9,00 for the row that has 9 in it. But the strange thing is the row that has 89.5 in it now just returns €89,00. So somewhere in the code it rounds the numbers down.
Does anyone know how to get the price to show just €9,00 and €89,50 respectively.
I tried the following codes as well:
SELECT ROUND(VerkoopPP40,2) AS RoundedPrice
As database query. That didn't work.
$prijzen = CAST($prijzen as decimal(2,2));
Also didn't work. Any more ideas?
Don't know if this will help you, but found in the comments of the PHP doc : "To prevent the rounding that occurs when next digit after last significant decimal is 5 (mentioned by several people)..." read more
$num1 = "89,5";
$num2 = str_replace(',', '.', $num1);
$price = number_format($num2, 2, '.', '');
echo"[ $price ]";
you should use number_format but in the right way let me explain it to you
you tried this with 89.5
$prijzen = number_format($foo, 2, ',', '');
but this is written for 89,5 not for 89.5
//this will work for you
$var = $row["VerkoopPP40"];
echo 'raw output from database is :'.$var;
$var = $var / 10;
echo 'after this step the number is :'.$var;
$var = number_format($var, 2, '.', '');
echo 'after this step the number is :'.$var;
number_format(the input number, decimal places, 'the divider between whole numbers and decimals', '')
What's the simple way to remove more than 1 decimal number from source number .
for example source numbers are :
1st source number is : 56.48216585224
2nd source number is: 93
Output must be :
1st output : 56.4
2nd output: 93
numbers are not static
what's the simple way ?
If you don't want rounding, then:
$number = 56.48216585224;
echo substr($number, 0, strpos($number, '.')+2); // output: 56.4
Otherwise:
Use php round() or number_format()
http://php.net/manual/en/function.round.php
http://php.net/manual/en/function.number-format.php
Examples:
$number = 56.48216585224;
echo number_format($number, 1, '.', ''); // Output: 56.5
echo round($number, 1); // Output: 56.5
I will suggest this PHP code for your requirement:
$n = 56.48216585224;
$m = floor($n * 10) / 10; // $m = 56.4 now
You can try the following
print(quickFormat("56.48216585224"));
print(quickFormat("93"));
function quickFormat($number) {
$number = explode(".", $number);
if (isset($number[1])) {
return $number[0] . "." . $number[1]{0};
} else {
return $number[0] ;
}
}
Output
56.4
93
Is there any slick way to round down to the nearest significant figure in php?
So:
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";
}
Unfortunately this fails horribly when $number is 0, but it does produce the expected result for positive integers. And it is a math-only solution.
Here's a pure math solution. This is also a more flexible solution if you ever wanted to round up or down, and not just down. And it works on 0 :)
if($num === 0) return 0;
$digits = (int)(log10($num));
$num = (pow(10, $digits)) * floor($num/(pow(10, $digits)));
You could replace floor with round or ceil. Actually, if you wanted to round to the nearest, you could simplify the third line even more.
$num = round($num, -$digits);
If you do want to have a mathy solution, try this:
function floorToFirst($int) {
if (0 === $int) return 0;
$nearest = pow(10, floor(log($int, 10)));
return floor($int / $nearest) * $nearest;
}
Something like this:
$str = (string)$value;
echo (int)($str[0] . str_repeat('0', strlen($str) - 1));
It's totally non-mathy, but I would just do this utilizing sting length... there's probably a smoother way to handle it but you could acomplish it with
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;
}
A math based alternative:
$mod = pow(10, intval(round(log10($value) - 0.5)));
$answer = ((int)($value / $mod)) * $mod;
I know this is an old thread but I read it when looking for inspiration on how to solve this problem. Here's what I came up with:
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);
}
}
While the functions here worked, I needed significant digits for very small numbers (comparing low-value cryptocurrency to bitcoin).
The answer at Format number to N significant digits in PHP worked, somewhat, though very small numbers are displayed by PHP in scientific notation, which makes them hard for some people to read.
I tried using number_format, though that needs a specific number of digits after the decimal, which broke the 'significant' part of the number (if a set number is entered) and sometimes returned 0 (for numbers smaller than the set number).
The solution was to modify the function to identify really small numbers and then use number_format on them - taking the number of scientific notation digits as the number of digits for 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;
}
This function retains the significant digits as well as presents the numbers in easy-to-read format for everyone. (I know, it is not the best for scientific people nor even the most consistently length 'pretty' looking numbers, but it is overall the best solution for what we needed.)
How do I split a number by the decimal point in php?
I've got $num = 15/4; which turns $num into 3.75. I would like to split out the 3 and the 75 parts, so $int = 3 and $dec = 75. My non-working code is:
$num = 15/4; // or $num = 3.75;
list($int, $dec) = split('.', $num);
but that results in empty $int and $dec.
Thanks in advance.
If you explode the decimal representation of the number, you lose precision. If you don't mind, so be it (that's ok for textual representation). Take the locale into account! We Belgians use a comma (at least the non-programming ones :).
If you do mind (for computations e.g.), you can use the floor function:
$num = 15/4
$intpart = floor( $num ) // results in 3
$fraction = $num - $intpart // results in 0.75
Note: this is for positive numbers. For negative numbers you can invert the sign, use the positive approach, and reinvert the sign of the int part.
$num = 15/4; // or $num = 3.75;
list($int, $dec) = explode('.', $num);
Try explode
list($int,$dec)=explode('.', $num);
as you don't really need to use a regex based split. Split wasn't working for you as a '.' character would need escaping to provide a literal match.
$int = $num > 0 ? floor($num) : ceil($num);
$dec = $num - $int;
If you want $dec to be positive when $num is negative (like the other answers) you could do:
$dec = abs($num - $int);
$num = 3.75;
$fraction = $num - (int) $num;
In case when you don't want to lose precision, you can use these:
$number = 10.10;
$number = number_format($number, 2, ".", ",");
sscanf($number, '%d.%d', $whole, $fraction);
// you will get $whole = 10, $fraction = 10
This works for positive AND negative numbers:
$num = 5.7;
$whole = (int) $num; // 5
$frac = $num - (int) $num; // .7
$num = 15/4;
substr(strrchr($num, "."), 1)