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.
Related
I have to validate if a float number has maximum two digits.
I've tried a lot of methods but all fails in more or lase cases.
Last of them were:
//fails for 2638655.99
private function hasMoreThanTwoDecimals(string $number): bool
{
$number = abs($number);
$intPart = floor($number);
$floatPart = $number - $intPart;
return (strlen($floatPart) > 4);
}
OR
//fails for 36.62
private function hasMoreThanTwoDecimals(string $number): bool
{
return $number * 100 - floor($number * 100) > 0.00001;
}
What other methods do you use?
You can't determine the exact number of decimals with the float datatype, because the internal representation is binary. In binary, fx. 0.1 can not be represented exactly. That's why loops always should have integer increments.
for ($i = -1; $i < 1; $i += 0.1) {
if ($i == 0) {
echo "Zero is here!";
}
}
will never say "Zero is here!" because of binary rounding issues.
Using an Epsilon
You already tried to use an epsilon (a very small value) for thesholding (here a refactored version of your function):
private function hasMoreThanTwoDecimals(string $number): bool
{
$epsilon = 0.00001;
return fmod($number * 100, 1.0) > $epsilon;
}
but fails for some values. In that case, you need to increase your epsilon value.
String Arithmetic
The more precise way is to avoid float and use string representations instead. This is your best option, since - according to your function signature - your numbers are represented as strings already.
private function hasMoreThanTwoDecimals(string $number): bool
{
return bcmod(bcmul($number, '100'), '1.0') != 0;
}
This needs the BCMath module to be included in your PHP. A package supporting BCMath and other solutions is brick/math.
The Cheap Solution
However, if you really just need to probe the number and not are doing calculations, you can get the desired result with pattern matching using preg_match.
private function hasMoreThanTwoDecimals(string $number): bool
{
// Trailing 0 does not add to number of decimals
$number = rtrim($number, '0');
return preg_match('~\.\d\d\d~', $number);
}
You can explode the number using the . delimeter, then you return the length of the second part :
$num = 2638655.99;
echo strlen(explode('.',$num)[1]); // Echo 2
Taking the question literally, if a binary floating point number has a maximum of two decimal digits after the decimal point, the fractional part must be one of .0, .25, .5, or .75.
All other binary floating point numbers really have more decimal digits, although printout formatting may hide them. For example, the closest IEEE 754 64-bit binary number to 2638655.99 is 2638655.99000000022351741790771484375, which has more than two digits after the decimal point.
You could subtract the integer part and then test for the remainder being one of the four possibilities.
Alternatively, the real question may be how to determine whether displaying the number will show no more than two digits after the decimal point. If so, convert to string using the appropriate method, then locate the decimal point and count the digits after it, for example as suggested in this answer.
$res = preg_match("^[+-]?([0]{1}|[1-9]{1}[0-9]*)(\.?[0-9]{1,2})?$", $num) == true;
would be the best solution in my opinion. You can use signs (optional) and enforce that a number starts with only one zero.
Possible:
+0.10
+123.01
-1
123
Not possible:
00.0
0001.0
1.
123.123
Be aware that preg_match returns 0 if no match is found and false if an error occurred (preg_match)
you can use the number_format
number_format($number, 2, '.', '');
I want to round a number and I need a proper integer because I want to use it as an array key. The first "solution" that comes to mind is:
$key = (int)round($number)
However, I am unsure if this will always work. As far as I know (int) just truncates any decimals and since round($number) returns a float with theoretically limited precision, is it possible that round($number) returns something like 7.999999... and then $key is 7 instead of 8?
If this problem actually exists (I don't know how to test for it), how can it be solved? Maybe:
$key = (int)(round($number) + 0.0000000000000000001) // number of zeros chosen arbitrarily
Is there a better solution than this?
To round floats properly, you can use:
ceil($number): round up
round($number, 0): round to the nearest integer
floor($number): round down
Those functions return float, but from Niet the Dark Absol comment: "Integers stored within floats are always accurate, up to around 2^51, which is much more than can be stored in an int anyway."
round(), without a precision set always rounds to the nearest whole number. By default, round rounds to zero decimal places.
So:
$int = 8.998988776636;
round($int) //Will always be 9
$int = 8.344473773737377474;
round($int) //will always be 8
So, if your goal is to use this as a key for an array, this should be fine.
You can, of course, use modes and precision to specify exactly how you want round() to behave. See this.
UPDATE
You might actually be more interested in intval:
echo intval(round(4.7)); //returns int 5
echo intval(round(4.3)); // returns int 4
What about simply adding 1/2 before casting to an int?
eg:
$int = (int) ($float + 0.5);
This should give a predictable result.
Integers stored within floats are always accurate, up to around 253, which is much more than can be stored in an int anyway. I am worrying over nothing.
For My Case, I have to make whole number by float or decimal type
number. By these way i solved my problem. Hope It works For You.
$value1 = "46.2";
$value2 = "46.8";
// If we print by round()
echo round( $value1 ); //return float 46.0
echo round( $value2 ); //return float 47.0
// To Get the integer value
echo intval(round( $value1 )); // return int 46
echo intval(round( $value2 )); // return int 47
My solution:
function money_round(float $val, int $precision = 0): float|int
{
$pow = pow(10, $precision);
$result = (float)(intval((string)($val * $pow)) / $pow);
if (str_contains((string)$result, '.')) {
return (float)(intval((string)($val * $pow)) / $pow);
}
else {
return (int)(intval((string)($val * $pow)) / $pow);
}
}
Round to the nearest integer
$key = round($number, 0);
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)
I want to convert float value (Eg:1.0000124668092E+14) to Integer in php,what is the best method for this in php.output should be "100001246680920"
What do you mean by converting?
casting*: (int) $float or intval($float)
truncating: floor($float) (down) or ceil($float) (up)
rounding: round($float) - has additional modes, see PHP_ROUND_HALF_... constants
*: casting has some chance, that float values cannot be represented in int (too big, or too small), f.ex. in your case.
PHP_INT_MAX: The largest integer supported in this build of PHP. Usually int(2147483647).
But, you could use the BCMath, or the GMP extensions for handling these large numbers. (Both are boundled, you only need to enable these extensions)
I just want to WARN you about:
>>> (int) (290.15 * 100);
=> 29014
>>> (int) round((290.15 * 100), 0);
=> 29015
Use round()
$float_val = 4.5;
echo round($float_val);
You can also set param for precision and rounding mode, for more info
Update (According to your updated question):
$float_val = 1.0000124668092E+14;
printf('%.0f', $float_val / 1E+14); //Output Rounds Of To 1000012466809201
There is always intval() - Not sure if this is what you were looking for...
example: -
$floatValue = 4.5;
echo intval($floatValue); // Returns 4
It won't round off the value to an integer, but will strip out the decimal and trailing digits, and return the integer before the decimal.
Here is some documentation for this: -
http://php.net/manual/en/function.intval.php
Try this
<?php
$float_val = 1.0000124668092E+14;
echo intval($float_val);
?>
Use round, floor or ceil methods to round it to the closest integer, along with intval() which is limited.
http://php.net/manual/en/function.round.php
http://php.net/manual/en/function.ceil.php
http://php.net/manual/en/function.floor.php
I need to do this rather strange thing, let's say i have:
$number = rand(1, 9);
(This is just an example of what number it could be, in reality i get it in entirely different way)
And now i need "convert" that number to 0.2 or whatever number i got, basically it has to begin with 0 and be a float type of number.
PHP does not support explicit type casting in variable declaration. To convert the int to a float in the way you want to simply divide by 10:
$number = rand(1, 9) / 10;
See this page on PHP Type Juggling for more info. If you mix floats and ints or other types they will be re-casted. Exmple:
echo 10 + 2.5; // gives you 12.5, a float because of the types used
Edit: PHP does have explicit type casting, just not in variable declaration. But even if you cast an integer as a float, it won't display with a decimal place. To do that use PHP's number_format function instead:
echo number_format(10, 1); // gives you 10.0
Edit 2: If you simply want to make your number a decimal between 0 and 1 (such that 2 becomes 0.2, 25 becomes 0.25, etc.) you could use the following function:
function getNumAsDecimal($num) {
return ($num / pow(10, strlen((string)$num)));
}
So getNumAsDecimal(2) would return 0.2.
function Floatize(){
return (float) (rand(1, 9) / 10);
}
echo Floatize(); // will return something like 0.2 or 0.5 or 0.9
$number=(float)rand(1, 9)/10;
See PHP type casting.