Take off X amount of decimals from a number - php

I have let's say 0.00001004 or 0.00001
I am trying to choose and how decimal places to prune off and turn both of those so it returns 0.00001 both times.
I do not want it to round the number in anyway.
I've tried this but it is not giving me the desired results.
function decimalFix($number, $decimals) {
return floatval(bcdiv($number, 1, $decimals));
}
echo decimalFix(0.00001, 5); // returns "0"
Does anyone know what I can do? I can't have any rounding involved and I need it to return it as a float and not a string.

I don't know why you're so committed to losing precision, but here's some math to make that particular mistake in the way you wish to make it.
$derp = 0.000016;
function derp_round($derp, $len) {
$mul = pow(10, $len);
return floor($derp * $mul)/$mul;
}
var_dump(
$derp,
number_format($derp, 5),
sprintf("%.5f", $derp),
sprintf("%.5f", round($derp, 5, PHP_ROUND_HALF_DOWN)),
sprintf("%.5f", derp_round($derp, 5))
);
Output:
float(1.6E-5)
string(7) "0.00002"
string(7) "0.00002"
string(7) "0.00002"
string(7) "0.00001"

There's a function that does exactly this in the first comment on the PHP documentation for floor(). I'll copy it here in case it disappears from there, but credits go to seppili_:
function floordec($zahl,$decimals=2){
return floor($zahl*pow(10,$decimals))/pow(10,$decimals);
}
Use it like:
$number = 0.00001004;
$rounded = floordec($number, 5);
var_dump($rounded); // float(0.00001)
Edit: There's a comment further down on that page by Leon Grdic that warns about float precision and offers this updated version:
function floordec($value,$decimals=2){
return floor($value*pow(10,$decimals)+0.5)/pow(10,$decimals);
}
Usage is the same.

Related

PHP round to integer

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);

PHP Reliable Calculating of Cube Root

It seems like a no brainer but I am having trouble to get this solved:
I would like to calculate a level based on given experience points (exp). Therefore I use the cube root formula and round down to the next whole number. The next level is reached when exp exactly reaches level^3. The number of levels is unlimited, so I would avoid having a pre-calculated lookup table.
When I use the standard php math
floor( pow( 10648, 1/3))
It returns 21 instead of 22. This is wrong since 21^3 gives 92161. The reason is that due to limited floating point precision pow(10648, 1/3) returns not exactly 22, instead it returns 21.9993112732.
You can check it out with the following snippet:
$lvl = pow( 10647, (float) 1 / 3);
print number_format( $lvl, 10);
This is my workaround. But I am not sure if this is bulletproof:
public static function getLevel($exp) {
$lvl = floor(pow($exp, (float) 1 / 3)); // calculate the level
if (pow($lvl + 1, 3) == $exp) { // make check
$lvl++; // correct
}
return $lvl;
}
Also it looks a bit fragile when it comes to the check. So the question remains:
Is there a reliable, efficient and bulletproof way of calculating cube root (of positive numbers).
Thanks.
I think this is the only modification your code needs:
public static function getLevel($exp) {
$lvl = floor(pow($exp, (float) 1 / 3));
if (pow($lvl + 1, 3) <= $exp) { // compare with <= instead of ==
$lvl++;
}
return $lvl;
}
If you need 100% reliable results, you should probably use the GMP library for arbitrary precision calculations.
The gmp_root function should do what you need. You'll need PHP version 5.6 or newer with the GMP extension enabled.
$num = gmp_init(10648);
$third_root = gmp_root($num, 3);
var_dump(gmp_strval($third_root)); // string(2) "22"
If the GMP library is inconvenient for you and you're guaranteed that your number has an integer root then you can try the following:
function getLevel($base, $root = 3.0) {
$exact = pow($base, 1.0 / $root);
$ceil = ceil($exact);
$floor = floor($exact);
if (pow($exact, $root) == $base) { return $exact; }
if (pow($ceil, $root) == $base) { return $ceil; }
if (pow($floor, $root) == $base) { return $floor; }
// Default: no integer root
return FALSE;
}
It checks the exact, floor, and ceil values of the result to find which is the correct answer. If it's not one of the three then the number has no integer root and defaults to FALSE.
Here's an example of it in action:
var_dump(getLevel(10648, 3)); // 22^3 => float(22)
var_dump(getLevel(16807, 5)); // 7^5 => float(7)
var_dump(getLevel(1, 3)); // Should always return 1 => float(1)
var_dump(getLevel(1, 99)); // Should always return 1 => float(1)
var_dump(getLevel(7)); // Has no integer 3rd root => bool(false)
Of course, you can make the function return $floor; or return $ceil; as the default case, but that's up to you.

rounding a number, NOT necessarily decimel PHP

I have a question.
I am using php to generate a number based on operations that a user has specified
This variable is called
$new
$new is an integer, I want to be able to round $new to a 12 digit number, regardless of the answer
I was thinking I could use
round() or ceil()
but I believe these are used for rounding decimel places
So, I have an integer stored in $new, when $new is echoed out I want for it to print 12 digits. Whether the number is 60 billion or 0.00000000006
If i understand correctly
function showNumber($input) {
$show = 12;
$input = number_format(min($input,str_repeat('9', $show)), ($show-1) - strlen(number_format($input,0,'.','')),'.','');
return $input;
}
var_dump(showNumber(1));
var_dump(showNumber(0.00000000006));
var_dump(showNumber(100000000000000000000000));
gives
string(12) "1.0000000000"
string(12) "0.0000000001"
string(12) "999999999999"

Unexpected round() return

I am trying to round down a number using PHP's round() function. Here is the code I am using:
$line_item_price = 13.775;
echo round($line_item_price, 2, PHP_ROUND_HALF_DOWN);
Now when I run the code like this I am hoping to get the output 13.77, except I am getting 0 (or nothing -- not sure which yet).
Now when I remove the PHP_ROUND_HALF_DOWN I get 13.78. Anyone see what I am doing wrong here? It seems like this should be working correctly.
The mode parameter was introduced in version 5.3, therefore it will not work for you. You'll have to find a custom function to do what you are looking for.
You are using a function that is not yet available in your current version of PHP. One way to solve this problem is using the floor function.
$line_item_price = 13.775;
echo floor($line_item_price * 100) / 100;
What I'm doing here is too first multiply the value with 100 and then floor the value. This will give you a rounded down value with the precision of 2. Then to get the correct value you need to devide with 100.
The number 100 comes from the power(10, desired precision)
can you not just do:
echo round($line_item_price, 2)
?
I'm not 100% sure but I think the ROUND_HALF_DOWN etc are for fractions such as 1.5, 2.5 and integers.
Here is a way to do it:
$num = 13.775;
$tmp = intval($num*1000);
$dec = $tmp % 10;
if ($dec > 5) {
$rounded = (1+intval($tmp/10))/100;
} else {
$rounded = intval($tmp/10)/100;
}
echo $rounded,"\n";
This gives : 13.77 for $num=13.775 and 13.78 for $num=13.776
Actually, I'm kind of surprised that it works at all, since the number 13.775 is not exactly representable in floating point:
$ php -r 'printf("%.40f\n", 13.775);'
13.7750000000000003552713678800500929355621
Indeed, it seems that round() is a bit lax about what counts as "half":
$ php -r 'echo round(13.77500000000001, 2, PHP_ROUND_HALF_DOWN) . "\n";'
13.77
Anyway, if your PHP doesn't support PHP_ROUND_HALF_DOWN, here's a simple kluge that gives approximately the same functionality:
function round_half_down ( $num, $digits ) {
$mul = pow( 10, $digits );
return ceil( $num * $mul - 0.5 ) / $mul;
}
This does turn out to work as one would naively expect, but is slightly stricter than round(): round_half_down(13.775, 2) == 13.77, but round_half_down(13.77500000000001, 2) == 13.78. Also, as a curious edge case, round_half_down(0.001, 2) returns -0. If you don't like that, you can always pass the return value through sprintf("%.{$digits}F") to format it nicely.

How can I make sure a float will always be rounded up with PHP?

I want to make sure a float in PHP is rounded up if any decimal is present, without worrying about mathematical rounding rules. This function would work as follows:
1.1 to 2
1.2 to 2
1.9 to 2
2.3 to 3
2.8 to 3
I know the round() function exists but I don't see any function for rounding up if any decimal is found. Is there any easy way to do this?
Use the ceil function:
$number = ceil(1.1); //2
I know this is an old topic, however it appears in Google. I will extend Blake Plumb's answer regarding precision.
ceil(1024.321 * 100) / 100;
Multiplying by 100 and dividing by 100 only works with one-hundredths. This isn't accurate on tenths, one-thousandths, one-hundred thousandths, etc.
function round_up($number, $precision = 2)
{
$fig = pow(10, $precision);
return (ceil($number * $fig) / $fig);
}
Results:
var_dump(round_up(1024.654321, 0)); // Output: float(1025)
var_dump(round_up(1024.654321, 1)); // Output: float(1024.7)
var_dump(round_up(1024.654321, 2)); // Output: float(1024.66)
var_dump(round_up(1024.654321, 3)); // Output: float(1024.655)
var_dump(round_up(1024.654321, 4)); // Output: float(1024.6544)
var_dump(round_up(1024.654321, 5)); // Output: float(1024.65433)
var_dump(round_up(1024.654321, 6)); // Output: float(1024.654321)
Notes:
Thanks for the contributions from Joseph McDermott and brandom for improving my original snippet.
The official Ceil function will do that for you.
Taken from the example:
<?php
echo ceil(4.3); // 5
echo ceil(9.999); // 10
echo ceil(-3.14); // -3
?>
I know this question has long since been answered, but it came up when I did a google search on the topic. If you want to round up with precision, then a good method would be to use the ceil function and times the number by how many decimal points you want to represent and then divide by that number.
ceil(1024.321*100)/100
would produce 1024.33
I like Ash's response, although I would have:
$fig = (int) str_pad('1', $precision + 1, '0');
Makes sense that if I provide precision '2', I would expect it rounded to 2 decimal places. Matter of choice though I suppose. Thanks for the answer Ash, works well.

Categories