Round integer to nearest multiple of 5 in PHP - php

Searching for a function ro round numbers to the nearest multiple of 5
22 -> 20
23 -> 25
40 -> 40
46 -> 45
48 -> 50
and so on.
Tried this which always returns the higher value:
5 * ceil($n / 5);

Use round() instead of ceil().
5 * round($n / 5);
ceil() rounds a floating point number up to its next integer in sequence. round() will round to the nearest integer using standard rounding rules.

Back to maths, since round works with decimals, multiply by 5 and divide by 10 and then round, it. Multiply by 5 again to get what u want. (Other answer works as well, just a different way of looking at it)
function round_5($in)
{
return round(($in*2)/10)*5;
}
echo round_5(48);
See if this helps

Well, facing this issue while helping make an POS for a Canadian company, came up with this solution, hope it helps someone. (Canada removed the penny in 2012). Also includes for doing tax included pricing, just pass '1' as second argh.
//calculate price and tax
function calctax($amt,$tax_included = NULL){
$taxa = 'tax rate 1 here';
$taxb = 'tax rate 2 here';
$taxc = ($taxa + $taxb) + 1;
if(is_null($tax_included)){
$p = $amt;
}else{
$p = number_format(round($amt / $taxc,2),2);
}
$ta = round($p * $taxa,2);
$tb = round($p * $taxb,2);
$sp = number_format(round($p+($ta + $tb),2),2);
$tp = number_format(round(($sp*2)/10,2)*5,2);
$ret = array($ta,$tb,$tp);
return $ret;
}

Related

What's the most efficient way of randomly picking a floating number within a specific range? [duplicate]

How does one generate a random float between 0 and 1 in PHP?
I'm looking for the PHP's equivalent to Java's Math.random().
You may use the standard function: lcg_value().
Here's another function given on the rand() docs:
// auxiliary function
// returns random number with flat distribution from 0 to 1
function random_0_1()
{
return (float)rand() / (float)getrandmax();
}
Example from documentation :
function random_float ($min,$max) {
return ($min+lcg_value()*(abs($max-$min)));
}
rand(0,1000)/1000 returns:
0.348 0.716 0.251 0.459 0.893 0.867 0.058 0.955 0.644 0.246 0.292
or use a bigger number if you want more digits after decimal point
class SomeHelper
{
/**
* Generate random float number.
*
* #param float|int $min
* #param float|int $max
* #return float
*/
public static function rand($min = 0, $max = 1)
{
return ($min + ($max - $min) * (mt_rand() / mt_getrandmax()));
}
}
update:
forget this answer it doesnt work wit php -v > 5.3
What about
floatVal('0.'.rand(1, 9));
?
this works perfect for me, and it´s not only for 0 - 1 for example between 1.0 - 15.0
floatVal(rand(1, 15).'.'.rand(1, 9));
function mt_rand_float($min, $max, $countZero = '0') {
$countZero = +('1'.$countZero);
$min = floor($min*$countZero);
$max = floor($max*$countZero);
$rand = mt_rand($min, $max) / $countZero;
return $rand;
}
example:
echo mt_rand_float(0, 1);
result: 0.2
echo mt_rand_float(3.2, 3.23, '000');
result: 3.219
echo mt_rand_float(1, 5, '00');
result: 4.52
echo mt_rand_float(0.56789, 1, '00');
result: 0.69
$random_number = rand(1,10).".".rand(1,9);
function frand($min, $max, $decimals = 0) {
$scale = pow(10, $decimals);
return mt_rand($min * $scale, $max * $scale) / $scale;
}
echo "frand(0, 10, 2) = " . frand(0, 10, 2) . "\n";
This question asks for a value from 0 to 1. For most mathematical purposes this is usually invalid albeit to the smallest possible degree. The standard distribution by convention is 0 >= N < 1. You should consider if you really want something inclusive of 1.
Many things that do this absent minded have a one in a couple billion result of an anomalous result. This becomes obvious if you think about performing the operation backwards.
(int)(random_float() * 10) would return a value from 0 to 9 with an equal chance of each value. If in one in a billion times it can return 1 then very rarely it will return 10 instead.
Some people would fix this after the fact (to decide that 10 should be 9). Multiplying it by 2 should give around a ~50% chance of 0 or 1 but will also have a ~0.000000000465% chance of returning a 2 like in Bender's dream.
Saying 0 to 1 as a float might be a bit like mistakenly saying 0 to 10 instead of 0 to 9 as ints when you want ten values starting at zero. In this case because of the broad range of possible float values then it's more like accidentally saying 0 to 1000000000 instead of 0 to 999999999.
With 64bit it's exceedingly rare to overflow but in this case some random functions are 32bit internally so it's not no implausible for that one in two and a half billion chance to occur.
The standard solutions would instead want to be like this:
mt_rand() / (getrandmax() + 1)
There can also be small usually insignificant differences in distribution, for example between 0 to 9 then you might find 0 is slightly more likely than 9 due to precision but this will typically be in the billionth or so and is not as severe as the above issue because the above issue can produce an invalid unexpected out of bounds figure for a calculation that would otherwise be flawless.
Java's Math.random will also never produce a value of 1. Some of this comes from that it is a mouthful to explain specifically what it does. It returns a value from 0 to less than one. It's Zeno's arrow, it never reaches 1. This isn't something someone would conventionally say. Instead people tend to say between 0 and 1 or from 0 to 1 but those are false.
This is somewhat a source of amusement in bug reports. For example, any PHP code using lcg_value without consideration for this may glitch approximately one in a couple billion times if it holds true to its documentation but that makes it painfully difficult to faithfully reproduce.
This kind of off by one error is one of the common sources of "Just turn it off and on again." issues typically encountered in embedded devices.
Solution for PHP 7. Generates random number in [0,1). i.e. includes 0 and excludes 1.
function random_float() {
return random_int(0, 2**53-1) / (2**53);
}
Thanks to Nommyde in the comments for pointing out my bug.
>>> number_format((2**53-1)/2**53,100)
=> "0.9999999999999998889776975374843459576368331909179687500000000000000000000000000000000000000000000000"
>>> number_format((2**53)/(2**53+1),100)
=> "1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
Most answers are using mt_rand. However, mt_getrandmax() usually returns only 2147483647. That means you only have 31 bits of information, while a double has a mantissa with 52 bits, which means there is a density of at least 2^53 for the numbers between 0 and 1.
This more complicated approach will get you a finer distribution:
function rand_754_01() {
// Generate 64 random bits (8 bytes)
$entropy = openssl_random_pseudo_bytes(8);
// Create a string of 12 '0' bits and 52 '1' bits.
$x = 0x000FFFFFFFFFFFFF;
$first12 = pack("Q", $x);
// Set the first 12 bits to 0 in the random string.
$y = $entropy & $first12;
// Now set the first 12 bits to be 0[exponent], where exponent is randomly chosen between 1 and 1022.
// Here $e has a probability of 0.5 to be 1022, 0.25 to be 1021, etc.
$e = 1022;
while($e > 1) {
if(mt_rand(0,1) == 0) {
break;
} else {
--$e;
}
}
// Pack the exponent properly (add four '0' bits behind it and 49 more in front)
$z = "\0\0\0\0\0\0" . pack("S", $e << 4);
// Now convert to a double.
return unpack("d", $y | $z)[1];
}
Please note that the above code only works on 64-bit machines with a Litte-Endian byte order and Intel-style IEEE754 representation. (x64-compatible computers will have this). Unfortunately PHP does not allow bit-shifting past int32-sized boundaries, so you have to write a separate function for Big-Endian.
You should replace this line:
$z = "\0\0\0\0\0\0" . pack("S", $e << 4);
with its big-endian counterpart:
$z = pack("S", $e << 4) . "\0\0\0\0\0\0";
The difference is only notable when the function is called a large amount of times: 10^9 or more.
Testing if this works
It should be obvious that the mantissa follows a nice uniform distribution approximation, but it's less obvious that a sum of a large amount of such distributions (each with cumulatively halved chance and amplitude) is uniform.
Running:
function randomNumbers() {
$f = 0.0;
for($i = 0; $i < 1000000; ++$i) {
$f += \math::rand_754_01();
}
echo $f / 1000000;
}
Produces an output of 0.49999928273099 (or a similar number close to 0.5).
I found the answer on PHP.net
<?php
function randomFloat($min = 0, $max = 1) {
return $min + mt_rand() / mt_getrandmax() * ($max - $min);
}
var_dump(randomFloat());
var_dump(randomFloat(2, 20));
?>
float(0.91601131712832)
float(16.511210331931)
So you could do
randomFloat(0,1);
or simple
mt_rand() / mt_getrandmax() * 1;
what about:
echo (float)('0.' . rand(0,99999));
would probably work fine... hope it helps you.

How to convert 11,22,33 into 10, 20 and 30 in PHP?

I don't know how to title the question correctly (please tell me what this kind of number called).
I'd like to convert from 2 digits number into a 10 divisible number. For example, I expect:
15 to become 10
23 to become 20
38 to become 30
999 to become 900
9999 to become 9000
I tried searching for the solution on google but I don't know how to type the proper word.
Easy, use the PHP floor function: http://php.net/manual/en/function.floor.php
floor($number/10) * 10
I wrote a simple function should work:
<?php
function roundDown($var){
$len = strlen($var)-1;
$divide = 1;
for($i=1;$i<=$len;$i++){
$divide .= 0;
}
return floor($var/$divide)*$divide;
}
echo roundDown(9999);
Easiest way is divide by ten, then floor value and multiply by ten. (Floor method - phpdocs)
floor($number/10)*10
Use round:
echo round(1241757, -6); // 1000000
from http://php.net/manual/en/function.round.php
You are looking for the "one significant figure".
I think this answer provides a good solution:
How to round down to the nearest significant figure in php
Short form:
$x = $y - $y % pow(10, floor(log10($y)));

Rounding to nearest fraction (half, quarter, etc.)

So, I need to create the following functions but my head can't think of any possibility in PHP without complicated math.
Round always up to the nearest decimal (1.81 = 1.90, 1.89 = 1.90, 1.85 = 1.90)
Round always down to the nearest decimal (1.81 = 1.80, 1.89 = 1.80, 1.85 = 1.80)
Round always up to the nearest x.25 / x.50 / x.75 / x.00 (1.81 = 2, 1.32 = 1.50)
Round always down to the nearest x.25 / x.50 / x.75 / x.00 (1.81 = 1.75, 1.32 = 1.25)
Round always up to the nearest x.50 / 1 (1.23 = 1.50, 1.83 = 2)
Round always down to the nearest x.50 / 1 (1.23 = 1, 1.83 = 1.50)
I have searched on Google for 2 hours now and the only things that came up were Excel forums. Is it possible with some simple lines of PHP?
Since you're looking for fourths (.00, .25, .50, .75), multiply your number by 4, round to nearest whole number as desired (floor if down, ceil if up), then divide by 4.
1.32, down to nearest fourth:
1.32 * 4 = 5.28
floor(5.28) = 5.00
5.00 / 4 = 1.25
Same principle applies for any other fractions, such as thirds or eighths (.0, .125, .25, .375, .5, .625, .75, .875). For example:
1.77, up to nearest eighth:
1.77 * 8 = 14.16
ceil(14.16) = 15.00
15.00 / 8 = 1.875
Just for fun, you could write a function like this:
function floorToFraction($number, $denominator = 1)
{
$x = $number * $denominator;
$x = floor($x);
$x = $x / $denominator;
return $x;
}
echo floorToFraction(1.82); // 1
echo floorToFraction(1.82, 2); // 1.5
echo floorToFraction(1.82, 3); // 1.6666666666667
echo floorToFraction(1.82, 4); // 1.75
echo floorToFraction(1.82, 9); // 1.7777777777778
echo floorToFraction(1.82, 25); // 1.8
Please note that the answer isn't really water tight. Since we're dealing with floats here it's not guaranteed that when you divide the rounded number by the denominator it returns a neatly round number. It may return 1.499999999999 instead of 1.5. It's the nature of floating point numbers.
Another round is needed before returning the number from the function.
Just in case someone lands here from google like I did :)
According to the mround() function in Excel:
function MRound($num,$parts) {
$res = $num * $parts;
$res = round($res);
return $res /$parts;
}
echo MRound(-1.38,4);//gives -1.5
echo MRound(-1.37,4);//gives -1.25
echo MRound(1.38,4);//gives 1.5
echo MRound(1.37,4);//gives 1.25
Look at example #3 on here and it is half of your solution - http://php.net/manual/en/function.round.php

Use PHP to round floats that aren't like 1.05

Is it possible to round a number where if it's .5, just leave it, anything below .5 round down, anything above .5 round up?
For example:
5.0 * 1.35 = 6.75 // leave it
5.2 * 1.35 = 7.02 // round down to 7.00
5.5 * 1.35 = 7.56 // round up to 8.00
I've formatted with round($n,0, PHP_ROUND_HALF_UP) where $n is the product from the above calc , which leaves 6.75 but returns 7.02 for the next one. I also tried round($n,-1, PHP_ROUND_HALF_UP) which gives me the 7.00 on the second calc but then of course won't return a 6.75 for the first, instead it returns 680.
This is a ticket markup calculation where the user enters the first number and is multiplied by the second. I actually remove the decimal because they don't want to see it, and they want this sort of customized rounding on the result.
function myround($num, $prec) {
$rhu = round($num, $prec, PHP_ROUND_HALF_UP);
$rhd = round($num, $prec, PHP_ROUND_HALF_DOWN);
return ($rhu + $rhd) / 2;
}
Works for any precision you like. For hundreth's place, as in the example, $prec would need to be 2.
The only way to determine the value of the last non-zero digit of a given floating point number in PHP is to convert it to a string.
$str = (string) $float;
$result = ($str[strlen($str) - 1] == 5) ? $float : round($float);
Example
Of course, no matter what you do it will be subject to a small margin of error because of the floating point precision issue.
$n = round($n, 2);
if($n % .05 != 0 || $n % .1 == 0)
{
$n = round($n);
}
Does this work for you? I'm assuming the 5 you speak of is the hundredth digit, and if it's not 5 then you want a whole number.

round number to nearest 0.2 with PHP

I'm creating this rating system using 5-edged stars. And I want the heading to include the average rating. So I've created stars showing 1/5ths. Using "1.2" I'll get a full star and one point on the next star and so on...
But I haven't found a good way to round up to the closest .2... I figured I could multiply by 10, then round of, and then run a switch to round 1 up to 2, 3 up to 4 and so on. But that seems tedious and unnecessary...
round(3.78 * 5) / 5 = 3.8
A flexible solution
function roundToNearestFraction( $number, $fractionAsDecimal )
{
$factor = 1 / $fractionAsDecimal;
return round( $number * $factor ) / $factor;
}
// Round to nearest fifth
echo roundToNearestFraction( 3.78, 1/5 );
// Round to nearest third
echo roundToNearestFraction( 3.78, 1/3 );
function round2($original) {
$times5 = $original * 5;
return round($times5) / 5;
}
So your total is 25, would it be possible to not use floats and use 1->25/25? That way there is less calculations needed... (if any at all)
Why is everyone giving solutions that require a deeper inspection or conversion? Want 0.2? Then:
round($n / 0.2) * 0.2; // $n = 3.78 / 0.2 = 18.9 (=) 19 * 0.2 = 3.8 //
Want 5? Then:
round($n / 5) * 5; // $n = 17 / 5 = 3.4 (=) 3 * 5 = 15 //
It's as simple as that.

Categories