Kindly refer: PHP Division Float Value Issue
With reference to the Question I have wrote the following code. Can this be done in different way or less code than this.?
The following will help when any of the two given value are lesser than 1 with decimal values. Is this a good practice?
<?php
$First_Value = 0.005;
$Second_Value = 0.1;
// Check the First Value for Decimal
$First_Whole = floor($First_Value); // 0
$First_Fraction = $First_Value - $First_Whole; // .005
// Check the Second Value for Decimal
$Second_Whole = floor($Second_Value); // 0
$Second_Fraction = $Second_Value - $Second_Whole; // .1
// Multiply with 100 becaus ethe decimal is restricted to 3 digit so multiply with 100 works
if(($First_Whole == 0) || ($Second_Whole == 0)){
$First_Value = $First_Value*100; // 0.5
$Second_Value = $Second_Value*100; // 10
}
echo $tableCount = $Second_Value / $First_Value; // 20
?>
You don't need to do any of that calculation. just do the last division.
...
$value1 = .005;
$value2 = .1;
echo $value1 / $value2;
results in 20
If you are trying to get just 2 decimals you can use number format after dividing. If you are trying to format before dividing then you should still be able to number format. If however, you cannot then why not just multiply both numbers by 1000 (three decimals) % by 1 and minus the difference of the mod from the actual. that will give you 3 in this case, divide back by 1000
[EDIT]
to get the remainder do the following example
...
$v = .0055;
$d = .1;
$a = $d/$v;
$s = $a % ceil($a);
$r = $a - $s;
answer = .18181818181818181...
Related
I want to create an array in PHP by dividing a number. So for example when I have the number 200 and I divide it through 0,10, I need to get an array with 2k entries of 0,10.
But when I have a division like 233,12 / 0,10, I also need the array but the last possible entry needs to be a bit higher so that it fills the sum up.
Actually I have no code. This is too complex for me. Maybe someone has an idea. I've did everything around this but got really stuck here...
$number = 200;
$divider = 0.10;
So you want to have an array with 2k entries each having the value 0.1 in them?
So something like
$number = 200;
$divider = 0.1;
$totalArraySize = $number / $divider;
$result = [];
$result = array_fill(0, $totalArraySize, $divider);
However to make it slightly bigger in case of (for example) 233,12/0,1 you would simply need to ceil() the $totalArraySize to round it up to the nearest full integer. And to make sure that the last entry has the difference you basicly need to calculate it. You get it by taking what you expect to be the sum and subtract the values you know to be right. So (totalSize - 1) * 0,1 .. would give you in this example 233,1 so the last entry would be then 233,12 - 233,1 = 0,02
$number = 233,12;
$divider = 0.1;
$totalArraySize = ceil($number / $divider);
$wasRoundUp = $number % 1 === 0
$result = [];
$result = array_fill(0, $totalArraySize, $divider);
if ($wasRoundUp)
$result[$totalArraySize] = $number - (($totalArraySize - 1) * 0,1)
Edit: Actually I realised that my logic to see if it was round up was wrong. I cannot rely on modulo 1 division here as 233,1 would be divisible by 0.1 in an even amount. So we need to check if totalArraySize != ($number / divider).
So new code would be
$number = 233,12;
$divider = 0.1;
$totalArraySize = ceil($number / $divider);
$wasRoundUp = $totalArraySize != ($number / $divider);
$result = [];
$result = array_fill(0, $totalArraySize, $divider);
if ($wasRoundUp)
$result[$totalArraySize] = $number - (($totalArraySize - 1) * 0,1)
Edit 2:
To reflect the question in the comment and "fix" an issue with the code here's the new answer. To fill up the last entry it now takes the divider value and not hardcoded 0.1 which would have to be changed correctly. And due to floating point calculations you would need to round the last value to two decimal points. I cannot guarantee if thats the best aproach tho to avoid the floating point rounding issue you might get there
$number = 164.85;
$divider = 0.2;
$totalArraySize = ceil($number / $divider);
$wasRoundUp = $totalArraySize != ($number / $divider);
$result = array_fill(0, $totalArraySize, $divider);
if ($wasRoundUp)
$result[$totalArraySize] = round($number - (($totalArraySize - 1) * $divider), 2);
I am trying to divide number to geners but if after that its less than 16 I want it to add the numbers from the less to 16 to the first gener in foreach.
$geners = explode(",", $post['geners']); // $post['geners'] = 12,26,988
$count = count($geners); // For example : 3
$calc = (16 / $count); / 5.6666
$total_each = number_format($calc, 0); // 5
$total = ( $count * $total_each); // 15
foreach ($geners as $key=>$gener){
$gener_each = $total_each;
if($total < 16){ // if 15 < 16
$minus_16 = 16 - $total; // 15-16 = 1
$gener_each[0]=$gener_each[0]+$minus_16; // First gener need to add $minus_16
}
echo $gener_each; // Need to be 6,5,5
}
It sounds like you need to divide 16 by an arbitrary number, create an array holding the same number of instances of that result as you have geners, round each instance of the divided result down to the nearest whole number, and then apply any remaining difference from a decimal result to the first in the set.
The following is untested, but have a look:
$geners = explode(',', $post['geners']);
$firstGener = current($geners);
$count = count($geners);
$calc = (16 / $count);
$floor = floor($calc);
$decimal = $calc - $floor;
$totals = [];
foreach ($geners as $gener) {
$totals[$gener] = $floor;
$totals[$firstGener] += $decimal;
}
//This is just in case a decimal result of an infinite number of digits, truncated by PHP itself, results in this value erroneously looking something like 5.9999999999999
$totals[$firstGener] = round($totals[$firstGener]);
//Since the value of $totals[$geners[0]] isn't done calculating until the completion of the above loop, presentation of each value needs to be handled in a separate one here:
foreach ($totals as $gener => $totals) {
echo "$gener - $total<br>";
}
I want to round up my variable if it's decimal larger than .3 and if it's lower or equal it will round down, for example if i have 1.34 it will round up to 2, if i have 1.29 it will round down to 1, and if i have 1.3 it will round down to 1. I don't know how to do this precisely, right now i'm using the round basic function like this:
$weight = $weight/1000;
if($weight < 1) $weight = 1;
else $weight = round($weight, 0, PHP_ROUND_HALF_DOWN);
If you manipulate the numbers a bit, you can figure out if the decimals are .3 or higher. You achieve this by flooring the value, and subtract that from the original value. Check if the result of that, multiplied by 10, is greater than 3. If it is, you've got something above x.3.
$number = 1.31;
$int = floor($number);
$float = $number-$int;
if ($float*10 > 3.1)
$result = ceil($number);
else
$result = $int;
echo $result; // 2
Live demo
I made you a little hack, here's the code
$weight = 5088;
$weight = $weight/1000;
if($weight < 1) {
$weight = 1;
} else {
// I get the last number (I treat the $weight as a string here)
$last_number = substr($weight, -1, 1);
// Then I get the precision (floating numbers)
$precision = strlen(substr(strrchr($weight, "."), 1));
// Then I convert it to a string so I can use some helpful string functions
$weight_str = (string) $weight;
// If the last number is less then 3
if ($last_number > 3)
// I change it to 9 I could just change it to 5 and it would work
// because round will round up if then number is 5 or greater
$weight_str[strlen($weight_str) -1] = 9;
}
}
// Then the round will round up if it's 9 or round down if it's 3 or less
$weight = round($weight_str, $precision);
echo $weight;
Maybe something like this function?
function roundImproved($value, $decimalBreakPart = 0.3) {
$whole = floor($value);
$decimal = $value - $whole;
$decimalPartLen = strlen($decimal) - 2;
return (number_format($decimal, $decimalPartLen) <= number_format($decimalBreakPart, $decimalPartLen) ? $whole : ceil($value));
}
Proof:
http://sandbox.onlinephpfunctions.com/code/d75858f175dd819de069a8a05611ac9e7053f07a
You can specify "break part" if you want.
I would like to ask how I can get the length of digits in an Integer. For example:
$num = 245354;
$numlength = mb_strlen($num);
$numlength should be 6 in this example. Somehow I can't manage it to work?
Thanks
EDIT: The example code above --^ and its respective method mb_strlen(); works just fine.
Maybe:
$num = 245354;
$numlength = strlen((string)$num);
Accepted answer won't work with the big numbers. The better way to calculate the length of any number is to invoke floor(log10($num) + 1) with a check for 0.
$num = 12357;
echo $num !== 0 ? floor(log10($num) + 1) : 1; // prints 5
It has multiple advantages. It's faster, you don't do the casting of types, it works on big numbers, it works with different number systems like bin, hex, oct.
The equation does the logarithm with base 10 then makes the floor of it and adds 1.
This solution can work independently on the base, so if you want to calculate the length of binary or hex just change the base of the logarithm.
Working fiddle
The accepted solution presents a problem when evaluating negative numbers.
It works with a positive number:
$num = 245354;
$numlength = strlen((string)$num);
// Result: 6
But with a negative number, the (-) is added to the count:
$num = -245354;
$numlength = strlen((string)$num);
// Result: 7
Quick workaround:
$num = -245354;
$numlength = strlen((string)abs($num));
// Result: 6
More elegant way :)
ceil(log10($num));
You could also use some basic math!
$digits = (int)(log($num,10)+1)
<?php
$num = 123;
$num2 = 1234;
$num3 = 12345;
function digits($num){
return (int) (log($num, 10) + 1);
}
echo "\n $num: " . digits($num); // 123: 3
echo "\n $num2:" . digits($num2); // 1234: 4
echo "\n $num3:" . digits($num3); // 12345: 5
echo "\n";
Another way to find out the length of a number in digits would be to divide the integer part of the number to 10 until it becomes 0.
Example:
2021/10 = 202.1
202/10 = 20.2
20/10 = 2
2/10 = 0.2
Code:
function numberGetLength($number) {
$count = 0;
while (intval($number) > 0) {
$number = intval($number) / 10;
$count += 1;
}
return $count
}
Just using some version of (int)(log($num,10)+1) fails for 10, 100, 1000, etc. It counts the number 10 as 1 digit, 100 as two digits, etc. It also fails with 0 or any negative number.
If you must use math (and the number is non-negative), use:
$numlength = (int)(log($num+1, 10)+1);
Or for a math solution that counts the digits in positive OR negative numbers:
$numlength = ($num>=0) ? (int)(log($num+1, 10)+1) : (int)(log(1-$num, 10)+1);
But the strlen solution is just about as fast in PHP.
In PHP types are loosely set and guessed, if you want to see something as a string if it is an integer, float, and (i have not tried this) bool then #Gorjunav is the most correct answer.
Reset the variable as a string
$stringNum = (string) $num;
Then you can go anything string related you want with it! And vice-versa for changing a string to an int
$number = (int) $stringNum;
and so on...
count only integer value
`<?php
$n1 =12345;
$n2 =123454.55;
$n3 =12345564.557;
echo "The Number you Type: ".$n1."<br>";
$count = 0;
while ($n1 != 0)
{
$n1 = $n1 / 10;
$n1 = intval($n1);
++$count;
}
echo "The Digit in a Number: ".$count;
}
?>`
echo strlen((string) abs($num)); // using **abs** it'll work with negative integers as well
Tested in PHP 4.4.9 - 8.0.0
$array = array(-1, 0, -0, 1, 4, 9, 10, -10, 20, -20, 100, -100);
foreach( $array as $key => $num ){
echo $key."\t{$num}\t=>\t".($num !== 0 ? floor(log10(abs($num)) + 1) : 1)."\n";
}
/* Output:
0 -1 => 1
1 0 => 1
2 0 => 1
3 1 => 1
4 4 => 1
5 9 => 1
6 10 => 2
7 -10 => 2
8 20 => 2
9 -20 => 2
10 100 => 3
11 -100 => 3
*/
The following function work for either integers or floats (works with PHP7+):
function digitsCount($number): int
{
$number = abs($number);
$numberParts = explode(".", $number);
return
strlen($numberParts[0]) +
(strlen($numberParts[1] ?? 0));
}
Time to test your math skills...
I'm using php to find the average of $num1, $num2, $num3 and so on; upto an unset amount of numbers. It then saves that average to a database.
Next time the php script is called a new number is added to the mix.
Is there a math (most likely algebra) equation that I can use to find the average of the original numbers with the new number included. Or do I need to save the original numbers in the database so I can query them and re-calculate the entire bunch of numbers together?
array_sum($values) / count($values)
If what you mean by average is the 'mean' and you don't want to store all numbers then store their count:
$last_average = 100;
$total_numbers = 10;
$new_number = 54;
$new_average = (($last_average * $total_numbers) + $new_number) / ($total_numbers + 1);
Average = Sum / Number of values
Just store all 3 values, there's no need for anything complicated.
If you store the Average and Sum then calculate Number of values you'll lose a little accuracy due to truncation of Average.
If you store the Average and Number of values then calculate Sum you'll lose even more accuracy. You have more margin for error in calculating a correct value for Number of values than Sum thanks to it being an integer.
<?php
function avrg()
{
$count = func_num_args();
$args = func_get_args();
return (array_sum($args) / $count);
}
?>
http://php.net/manual/en/function.array-sum.php#101727
Thought that I should share my function
function avg(array $values) {
$sum = array_sum($values);
$count = count($values);
return ($count !== 0)? $sum / $count: NAN;
}
echo avg([1, 2, 3, 4]); // 2.5
Will return the average and also take into account 0, for example dividing by zero always returns NaN (Not a number)
1/0 = NaN
0/0 = NaN
If you know the amount of numbers you can calculate the old sum, add the new one and divide by the old amount plus one.
$oldsum = $average * $amount;
$newaverage = ($oldsum + $newnum) / ($amount + 1);
Typically what you might do is save two pieces of information:
the sum of all the numbers
the count of numbers
Whenever you want to get the average, divide the sum by the count (taking care for the case of count == 0, of course). Whenever you want to include a new number, add the new number to the sum and increment the count by 1.
This is called a 'running average' or 'moving average'.
If the database stores the average and the number of values averaged, it will be possible to calculate a new running average for each new value.
function avgvals($avg_vals,$avg_delimiter=',') {
if ( (is_string($avg_vals) && strlen($avg_vals) > 2) && (is_string($avg_delimiter) && !empty($avg_delimiter)) ) {
$average_vals = explode($avg_delimiter, $avg_vals);
$return_vals = ( array_sum($average_vals) / count($average_vals) );
} elseif ( (is_string($avg_vals) && strlen($avg_vals) <= 2) && (is_string($avg_delimiter) && !empty($avg_delimiter)) ) {
$return_vals = $avg_vals;
} else {
$return_vals = FALSE;
}
return $return_vals;
}
Code:
function avg($list){
$sum = array_sum($list);
$count = count($list);
return ($count)? $sum / $count: NAN;
}
print ("Average: ".avg([1,2,3,4,5]));
Output:
Average: 3
You need to save all the original numbers in the database.