I want my variable's first decimal to always be rounded up. For example:
9.66 goes to 9.7
9.55 goes to 9.6
9.51 goes to 9.6
9.00000001 goes to 9.1
How do I do this?
Use round() with an optional precision and round type arguments, e.g.:
round($value, 1, PHP_ROUND_HALF_UP)
The optional second argument to round() is the precision argument and it specifies the number of decimal digits to round to. The third optional argument specifies the rounding mode. See the PHP manual for round for details.
Using round() does not always round up, even when using PHP_ROUND_HALF_UP (e.g. 9.00001 is not rounded to 9.1). You could instead try to use multiplication, ceil() and division:
ceil($value * 10.0) / 10.0
Since these are floating-point values, you might not get exact results.
I made couple tests and suggest the following answer with test cases
<?php
echo '9.66 (expected 9.7) => '.myRound(9.66).PHP_EOL;
echo '9.55 (expected 9.6) => '.myRound(9.55).PHP_EOL;
echo '9.51 (expected 9.6) => '.myRound(9.51).PHP_EOL;
echo '9.00000001 (expected 9.1) => '.myRound(9.00000001).PHP_EOL;
echo '9.9 (expected ??) => '.myRound(9.9).PHP_EOL;
echo '9.91 (expected ??) => '.myRound(9.91).PHP_EOL;
function myRound($value)
{
return ceil($value*10)/10;
}
I'm not a php programmer so will have to answer in "steps". The problem you have is the edge case where you have a number with exactly one decimal. (e.g. 9.5)
Here's how you could do it:
Multiply your number by 10.
If that's an integer, then return the original number (that's the edge case), else continue as follows:
Add 0.5
Round that in the normal way to an integer (i.e. "a.5" rounds up).
Divide the result by 10.
For step (2), sniffing around the php documentation reveals a function bool is_int ( mixed $var ) to test for an integer.
You will need a custom ceil() function, your requirements cannot be satisfied by the default function or by the round.
Use this: online test
You can use this technique. Just explode the given number / string, get the number which is next value / digit of the .. after getting this you need to increment that value and check if the value is greater than 9 or nor, if then divide that and add the carry to the first portion of the main number.
$var = '9.96';
$ar = explode(".", $var);
$nxt = substr($ar[1], 0, 1) + 1;
if($nxt > 9){
$tmp = (string) $nxt;
$num = floatval(($ar[0] + $tmp[0]).".".$tmp[1]);
}
else
$num = floatval($ar[0].".".$nxt);
var_dump($num); // float(10)
Related
php function round not working correctly.
I have number 0.9950.
I put code:
$num = round("0.9950", 2);
And I get 1.0? Why?? Why I can't get 0.99?
You can add a third parameter to the function to make it do what you need.
You have to choose from one of the following :
PHP_ROUND_HALF_UP
PHP_ROUND_HALF_DOWN
PHP_ROUND_HALF_EVEN
PHP_ROUND_HALF_ODD
This constants are easy enough to understand, so just use the adapted one :)
In your example, to get 0.99, you'll need to use :
<?php echo round("0.9950", 2, PHP_ROUND_HALF_DOWN); ?>
DEMO
When you round 0.9950 to two decimal places, you get 1.00 because this is how rounding works. If you want an operation which would result in 0.99 then perhaps you are looking for floating point truncation. One option to truncate a floating point number to two decimal places is to multiply by 100, cast to integer, then divide again by 100:
$num = "0.9950";
$output = (int)(100*$num) / 100;
echo $output;
0.99
This trick works because after the first step 0.9950 becomes 99.50, which, when cast to integer becomes just 99, discarding everything after the second decimal place in the original number. Then, we divide again by 100 to restore the original number, minus what we want truncated.
Demo
Just tested in PHP Sandbox... PHP seems funny sometimes.
<?php
$n = 16.90;
echo (100*$n)%100, "\n"; // 89
echo (int)(100*$n)%100, "\n"; // 89
echo 100*($n - (int)($n)), "\n"; // 90
echo (int)(100*($n - (int)($n))), "\n"; // 89
echo round(100*($n - (int)($n))), "\n"; // 90
I am trying to do a 2 digit precision in PHP Laravel project but it doesnt work. I have the value 1234666.6666667 that I want to make 1234666.66 but all the results I've seen in here or/and in other search pages.
This is my code:
$value = 1234666.6666667;
return round($value,2);
any other solution?
EDIT:
As I see, you actually want to floor number to 2 decimal points, not to round it, so this answer could help you:
$value = 1234666.6666667;
floor($value * 100) / 100; // returns 1234666.66
If you want 3 decimal points you need to multiple and divide with 1000, for 4 - with 10000 and etc.
You can use number_format, it convert value to string though, so you lose real float value:
$value = 1234666.6666667;
echo number_format($value, 2, '.', ''); // prints 1234666.67
Use this function.
function truncate($i) {
return floor($i*100) / 100.0;
}
Then you can do
$value = truncate(123.5666666); // 123.56
A pragmatic way is to use round($value - 0.05, 2), but even that gets you into hot water with some edge cases. Floating point numbers just don't round well. It's life I'm afraid. The closest double to 1234666.66 is
1234666.65999999991618096828460693359375
That's what $value will be after applying my formula! Really, if you want exact decimal precision, then you need to use a decimal type. Else use integer types and work in multiples of 100.
For the former choice, see http://de2.php.net/manual/en/ref.bc.php
$value = bcadd($value, 0, 2); // 1234666.6666667 -> 1234666.66
Another more exotic way to solve this issue is to use bcadd() with a dummy value for the $right_operand of 0,
This will give you 2 number after decimal.
I know of the PHP function floor() but that doesn't work how I want it to in negative numbers.
This is how floor works
floor( 1234.567); // 1234
floor(-1234.567); // -1235
This is what I WANT
truncate( 1234.567); // 1234
truncate(-1234.567); // -1234
Is there a PHP function that will return -1234?
I know I could do this but I'm hoping for a single built-in function
$num = -1234.567;
echo $num >= 0 ? floor($num) : ceil($num);
Yes intval
intval(1234.567);
intval(-1234.567);
Truncate floats with specific precision:
echo bcdiv(2.56789, 1, 1); // 2.5
echo bcdiv(2.56789, 1, 3); // 2.567
echo bcdiv(-2.56789, 1, 1); // -2.5
echo bcdiv(-2.56789, 1, 3); // -2.567
This method solve the problem with round() function.
Also you can use typecasting (no need to use functions),
(int) 1234.567; // 1234
(int) -1234.567; // -1234
http://php.net/manual/en/language.types.type-juggling.php
You can see the difference between intval and (int) typecasting from here.
another hack is using prefix ~~ :
echo ~~1234.567; // 1234
echo ~~-1234.567; // 1234
it's simpler and faster
Tilde ~ is bitwise NOT operator in PHP and Javascript
Double tilde(~) is a quick way to cast variable as integer, where it is called 'two tildes' to indicate a form of double negation.
It removes everything after the decimal point because the bitwise operators implicitly convert their operands to signed 32-bit integers. This works whether the operands are (floating-point) numbers or strings, and the result is a number
reference:
https://en.wikipedia.org/wiki/Double_tilde
What does ~~ ("double tilde") do in Javascript?
you can use intval(number); but if your number bigger than 2147483648 (and your machine/os is x64) all bigs will be truncated to 2147483648. So you can use
if($number < 0 )
$res = round($number);
else
$res = floor($number);
echo $res;
You can shift the decimal to the desired place, intval, and shift back:
function truncate($number, $precision = 0) {
// warning: precision is limited by the size of the int type
$shift = pow(10, $precision);
return intval($number * $shift)/$shift;
}
Note the warning about size of int -- this is because $number is potentially being multiplied by a large number ($shift) which could make the resulting number too large to be stored as an integer type. Possibly converting to floating point might be better.
You could get fancy with a $base parameter, and sending that to intval(...).
Could (should) also get fancy with error/bounds checking.
An alternative approach would be to treat number as a string, find the decimal point and do a substring at the appropriate place after the decimal based on the desired precision. Relatively speaking, that won't be fast.
See, I want to write a function that takes a float number parameter and rounds the float to the nearest currency value (a float with two decimal places) but if the float parameter has a zero fraction (that is, all zeroes behind the decimal place) then it returns the float as an integer (or i.e. truncates the decimal part since they're all zeroes anyways.).
However, I'm finding that I can't figure out how to determine if if a fraction has a zero fraction. I don't know if there's a PHP function that already does this. I've looked. The best I can think of is to convert the float number into an integer by casting it first and then subtract the integer part from the float and then check if the difference equals to zero or not.
if($value == round($value))
{
//no decimal, go ahead and truncate.
}
This example compares the value to itself, rounded to 0 decimal places. If the value rounded is the same as the value, you've got no decimal fraction. Plain and simple.
A little trick with PHPs type juggling abilities
if ($a == (int) $a) {
// $a has a zero fraction value
}
I think the best way:
if ((string)$value == (int)$value){
...
}
Example:
$value = 2.22 * 100;
var_dump($value == (int)$value); // false - WRONG!
var_dump($value == round($value)); // false - WRONG!
var_dump((string)$value == (int)$value); // true - OK!
function whatyouneed($number) {
$decimals = 2;
printf("%.".($number == (int)($number) ? '0' : $decimals)."F", $number);
}
So basically it's either printf("%.2F") if you want 2 decimals and printf("%.2F") if you want none.
Well, the problem is that floats aren't exact. Read here if you're interested in finding out why. What I would do is decide on a level of accuracy, for example, 3 decimal places, and base exactness on that. To do that, you multiply it by 1000, cast it to an int, and then check if $your_number % 1000==0.
$mynumber = round($mynumber *1000);
if ($mynumber % 1000==0)
{ isInt() }
Just so you know, you don't have to write a function to do that, there's already one that exists:
$roundedFloat = (float)number_format("1234.1264", 2, ".", ""); // 1234.13
If you want to keep the trailing .00, just omit the float cast (although it will return a string):
$roundedFloatStr = number_format("1234.000", 2, ".", ""); // 1234.00
example: 1.123 =>1 1.999 => 1
thanks.
$y = 1.235251;
$x = (int)$y;
echo $x; //will echo "1"
Edit:
Using the explicit cast to (int) is the most efficient way to to this AFAIK. Also casting to (int) will cut off the digits after the "." if the number is negative instead of rounding to the next lower negative number:
echo (int)(-3.75); //echoes "-3";
echo floor(-3.75); //echoes "-4";
floor()
will round a number down to the nearest integer.
EDIT: As pointed out by Mark below, this will only work for positive values, which is an important assumption. For negative values, you'd want to use ceil() -- but checking the sign of the input value would be cumbersome and you'd probably want to employ Mark's or TechnoP's (int) cast idea instead. Hope that helps.
You could use a bitwise operator.
Without:
echo 49 / 3;
>> 16.333333333333
With "| 0" bitwise:
echo 49 / 3 | 0;
>> 16
$y = 1.234;
list($y) = explode(".", "$y");
If your input can only be positive floats then as already mentioned floor works.
floor(1.2)
However if your integer could also be negative then floor may not give you what you want: it always rounds down even for negative numbers. Instead you can cast to int as another post mentioned. This will give you the correct result for both negative and positive numbers.
(int)-1.2
To remove all number after point use some php function
echo round(51.5); // Round the number, return 51.
echo floor(51.5); // Round down number, return 51.
echo ceil(51.3); // Round up number, return 52.