Can a do-while loop have multiple conditions? If so, I can't figure out why the code below is failing on all but the first condition.
Functions used...
function gcf($a,$b) {
$a = abs($a); $b = abs($b);
if( $a < $b) list($b,$a) = Array($a,$b);
if( $b == 0) return $a;
$r = $a % $b;
while($r > 0) {
$a = $b;
$b = $r;
$r = $a % $b;
}
return $b;
}
function factors($n){
$factors_array = array();
for ($x = 1; $x <= sqrt(abs($n)); $x++)
{
if ($n % $x == 0)
{
$z = $n/$x;
array_push($factors_array, $x, $z);
}
}
return $factors_array;
}
Code...
$a = $b;
do{
$a = mt_rand(8, 100);
$a_factors_array = factors($a);
$b = mt_rand(8, 100);
$b_factors_array = factors($b);
} while ($a == $b && count($a_factors_array) < 4 && count($b_factors_array) < 4 && gcf($a, $b) == 1);
echo $a . '<br>';
echo $b . '<br>';
echo count($a_factors_array) . '<br>';
echo count($b_factors_array) . '<br>';
echo gcf($a, $b) . '<br>';
I keep getting numbers for $a and $b that have less than 4 factors and have a GCF of 1. Any ideas?
You'll need || instead of &&. You want to repeat the loop as long as any one of your conditions is met. Currently the loop is only repeated if all of the conditions are met.
I think you have an ANDs where you meant an ORs:
do{
$a = mt_rand(8, 100);
$a_factors_array = factors($a);
$b = mt_rand(8, 100);
$b_factors_array = factors($b);
} while ($a == $b || count($a_factors_array) < 4 || count($b_factors_array) < 4 || gcf($a, $b) == 1);
With your way, the while stops if $a !== $b which is probably not what you want.
Related
I have a problem with my PHP script for calculating powers.
$A = $_POST["a"]; //Base number
$B = $_POST["b"]; //Value that POW of $A can't exceed. for example if A = 2, B = 1000, then highest solution = 512
for ($i = 1; $A <= $B; $i++) {
echo $i . ". ";
echo pow($A, $i);
echo '<br>';
}
With the example i mentioned above, i know this script would still display 1024 but the problem is it doesn't work at all. I tried doing this many other ways and nothing works for me... please any guidance is really appreciated.
Let's take the example of $A = 2; $B = 10; so you'd expect to get 2, 4, 8.
Your for loop has as condition, execute as long as $A <= $B.
Let us manually do some iterations:
Run 1: $A: 2, $B: 10, ($A <= $B): true, $i: 1, output: "1. 2<br>"
Run 2: $A: 2, $B: 10, ($A <= $B): true, $i: 2, output: "1. 4<br>"
Run 3: $A: 2, $B: 10, ($A <= $B): true, $i: 3, output: "1. 8<br>"
Run 4: $A: 2, $B: 10, ($A <= $B): true, $i: 4, output: "1. 16<br>"
Run 5: $A: 2, $B: 10, ($A <= $B): true, $i: 5, output: "1. 32<br>"
Run X: $A: 2, $B: 10, ($A <= $B): true, $i: X, output: "1. 2^X<br>"
As we can see, the tested condition $A <= $B is always true. How to fix this? One option is to update variable $A, like this:
$A = $_POST["a"]; //Base number
$B = $_POST["b"]; //Value that POW of $A can't exceed. for example if A = 2, B = 1000, then highest solution = 512
for ($i = 1; $A <= $B; $i++) {
$A = pow($A, $i);
if ($A <= $B) {
echo $i . ". ";
echo $A;
echo '<br>';
}
}
Another option would be to use a break condition:
$A = $_POST["a"]; //Base number
$B = $_POST["b"]; //Value that POW of $A can't exceed. for example if A = 2, B = 1000, then highest solution = 512
for ($i = 1; true; $i++) {
$A = pow($A, $i);
if ($A > $B) {
break;
}
echo $i . ". ";
echo $A;
echo '<br>';
}
This is an infinite loop, which usually gets written as
$A = $_POST["a"]; //Base number
$B = $_POST["b"]; //Value that POW of $A can't exceed. for example if A = 2, B = 1000, then highest solution = 512
$i = 1;
while (true) {
if ($A > $B) {
break;
}
echo $i . ". ";
$A = pow($A, $i);
echo $A;
echo '<br>';
$i++;
}
One last thing, since $A and $B get submitted by a client, you shouldn't assume they're numbers. You can simply cast them to numbers using:
$A = (int) $_POST['a'];
$B = (int) $_POST['b'];
How I personally would write that code:
// get variables
$base = (int) $_POST["a"];
$max = (int) $_POST["b"];
// validate input
if ($max < $base) {
echo 'error: Max number bigger than base number!<br>';
} elseif ($base < 2) {
echo 'error: Base number needs to be >= 2!<br>';
}
/** SOLUTION 1 - using `pow` */
// starting exponent
$exp = 1;
// assign $base^$exp to $result and test it against $max
while (($result = pow($base, $exp)) <= $max) {
// echo current row
echo $exp.'. '.$result.'<br>';
// increment exponent
$exp++;
}
/** SOLUTION 2 - using dynamic programming instead of calling `pow` in each iteration */
// multiply $result with the base and check against $max
for ($result = 1, $exp = 1; ($result *= $base) <= $max; $exp++) {
echo $exp.'. '.$result.'<br>';
}
/** In case you don't need the exponent:
for ($result = 1; ($result *= $base) <= $max;) {
echo $result.'<br>';
}
*/
Try to pick variables that explain what they're doing and add comments to explain what's happening.
$C = 1;
for ($i = 1; $C <= $B; $i++) {
$C = pow($A, $i);
if ($C <= $B) {
echo $i . ". " . $C . '<br>';
} else {
break;
}
}
Just added a variable $C that changes each time the loop runs so it can actually finish.
I have 5 variables $a $b $c $d $e . These variables has numerical values. Im trying to compare these variables where each variable will be compared to the rest and if the condition is true it echoes something. Here is my code
if ($a > ($b && $c && $d && $e)) {
$result = '<div>Im A</div>'
} else if ($b > ($a && $c && $d && $e)) {
$result = '<div>Im B</div>'
} else if ($c > ($a && $b && $d && $e)) {
$result = '<div>Im C</div>'
} else if ($d > ($a && $b && $c && $e)) {
$result = '<div>Im D</div>'
} else if ($e > ($a && $b && $c && $d)) {
$result = '<div>Im E</div>'
}
return $result;
The result stops at first condition even though it is false and it should pass it to other conditions.
Some different approach:
$a = 1;
$b = 3;
$c = 4;
$d = 5;
$e = 0;
// Make array [a=>1, b=>3...]
$arr = compact('a','b','c','d','e');
// Sort it in descending order with saving keys
arsort($arr);
// Get the 1st key
echo 'I\'m ' . strtoupper(key($arr)); // I'm D
First of all - you have parentheses around ($b && $c && $d && $e), this means that in $a > ($b && $c && $d && $e) the result of ($b && $c && $d && $e) will be counted first, and then will be compared to $a.
So, $a > ($b && $c && $d && $e) is not
$a is greater than $b and $a is greater than $c and etc.
it is
$a is greater than result of ($b and $c and $d and $e)
And result of $b and $c and $d and $e is either true or false.
So, in the end you compare $a > true or $a > false. According to value of $a you can get different results.
In a simple case, if you want to check if something is greater than anything else you need to write a condition like:
if ($a > $b && $a > $c && $a > $d && $a > $e) {
Other more tricky solutions you will find in other users' anwers.
You can iterate your five variables and keep track of the one with the highest value.
for ($i='a', $x = 0, $max = 'x'; $i <= 'e'; $i++) {
if ($$i > $$max) {
$max = $i;
}
}
$result = "<div>I'm " . strtoupper($max) . "</div>";
I think you should steer clear of if statements ;) Here's a solution without them that can be used with any number of variables. You could use the $key as an index into a list of functions and make the program extensible.
// Make the numbers into an array
$o = [$a, $b, $c, $d, $e];
// Find the highest value
$max = max($o);
// Look up the highest value to get the index
$key = array_search($max, $o);
// Now you know which one it is, you can do anything with it!
switch ($key) {
case 0: $result = '<div>Im A</div>'; break;
case 1: $result = '<div>Im B</div>'; break;
...
}
Try this:
$array = ['A'=>$a,'B'=>$b,' C'=>$c,'D'=>$d,'E'=> $e];
$maxs = array_keys($array, max($array));
foreach ($maxs as $maxi )
echo '<div>Im '.$maxi.'</div>."<br>"';
This way it covers cases were there are multiple max values.
Refer to this answer for more about how it works.
I use the following to find out the common divisors.
But in some case the count of divisors are not satisfied.
My Code :
$x = 66928;
$y = 66992;
$c_a = [];
$c_b = [];
$d = 1;
while ($d_a <= $x) {
if (is_int($x / $d)) $c_a[] = $d;
$d++;
}
$d = 1;
while ($d_b <= $y) {
if (is_int($y / $d)) $c_b[] = $d;
$d++;
}
echo count($c_a);
echo count($c_b);
// Output
$c_a = 20;
$c_b = 20;
Because, in some cases, it won't work.
Is this type of calculation is right ?
or any suggestions ?
As per asked in comment, to count the common factors of the two no. will be as like this.
<?php
$a = 66928;
$b = 66992;
$min = ($a < $b ) ? $a : $b;
$commomn_factors_count = 0;
for ($i = 1; $i < $min/2; $i++) {
if (($a%$i==0) && ($b%$i==0)) {
$commomn_factors_count++;
}
}
var_dump($commomn_factors_count);
You can you this code to get the fastest result to find the number of common divisors between two numbers:
// Function to calculate gcd of two numbers
function gcd($a, $b)
{
if ($a == 0)
return $b;
return gcd($b % $a, $a);
}
/* Function to calculate all common
* divisors of two given numbers
* a, b --> input integer numbers
*/
function commDiv($a, $b)
{
// find gcd of a, b
$n = gcd($a, $b);
// Count divisors of n.
$result = 0;
for ($i = 1; $i <= sqrt($n);
$i++)
{
// if 'i' is factor of n
if ($n % $i == 0)
{
// check if divisors
// are equal
if ($n / $i == $i)
$result += 1;
else
$result += 2;
}
}
return $result;
}
// Driver Code
$a = 10; $b = 15;
echo(commDiv($a, $b));
This question already has answers here:
Double? Integer? -- PHP
(2 answers)
Closed 8 years ago.
The code below generates two random decimal values, then subtracts them to get $c.
The do-while loop is trying to ensure that $c will not be a whole number. But I keep getting times where $c actually is a whole number.
do{
unset($a);
unset($b);
unset($c);
unset($adjuster);
unset($c_is_int);
$a = mt_rand(5, 75);
$b = mt_rand(5, 75);
$adjuster = mt_rand(2, 20);
$decimal_selector = mt_rand(1, 6);
if ($decimal_selector == 1){
$a = $a / 10;
$b = $b / 10;
}
if ($decimal_selector == 2){
$a = $a / 10;
$b = $b / 100;
}
if ($decimal_selector == 3){
$a = $a / 100;
$b = $b / 10;
}
if ($decimal_selector == 4){
$a = $a / 100;
$b = $b / 100;
}
if ($decimal_selector == 5){
$a = $a / 1000;
$b = $b / 1000;
}
if ($decimal_selector == 6){
$a = $a / 1000;
$b = $b / 100;
}
if($b < $a){
$b = $b + ($a - $b) + $adjuster;
}
$c = $b - $a;
if(intval($c) == $c) {
$c_is_int = 1;
} else {
$c_is_int = 0;
}
echo $a . '<br><br>';
echo $b . '<br><br>';
echo intval($c) . '<br>';
echo $c_is_int . '<br>';
echo $c . '<br><br>';
} while($c_is_int == 1);
The attached image shows the results of one of these failing times. Any ideas on where this is going wrong?
Why not check to see if the number has a decimal?
$c = 123.456;
if(strpos((string) $c, '.') !== FALSE) {
// is decimal/float/double
}
You can also just check to see if it's an int
if(is_int($c))
You want to keep in mind that the integer 3 and float 3.0 will compare as equal when using the ==.
Consider:
$c_is_int = $c == floor( $c );
...
while( $c_is_int )
The following code generates two random decimal values, then subtracts them to get $c.
$a = mt_rand(5, 75);
$b = mt_rand(5, 75);
$adjuster = mt_rand(2, 20);
do {
$decimal_selector = mt_rand(1, 6);
if ($decimal_selector == 1) {
$a = $a / 10;
$b = $b / 10;
}
if ($decimal_selector == 2) {
$a = $a / 10;
$b = $b / 100;
}
if ($decimal_selector == 3) {
$a = $a / 100;
$b = $b / 10;
}
if ($decimal_selector == 4) {
$a = $a / 100;
$b = $b / 100;
}
if ($decimal_selector == 5) {
$a = $a / 1000;
$b = $b / 1000;
}
if ($decimal_selector == 6) {
$a = $a / 1000;
$b = $b / 100;
}
if($b < $a)
$b = $b + ($a - $b) + $adjuster;
$c = $b - $a;
} while((is_int($a) == true && is_int($b) == true) || is_int($c) == true);
The do-while loop is trying to ensure that $a and $b are both not integers, and also that $c is not an integer. But I keep getting times where $c actually is an integer.
If I use gettype it keeps saying $c is a "double". Why, when $c ends up being something like 7?
EDIT:
I keep getting random infinite loops from this code below. Any ideas why?
do{
$a = mt_rand(5, 75);
$b = mt_rand(5, 75);
$adjuster = mt_rand(2, 20);
$decimal_selector = mt_rand(1, 6);
if ($decimal_selector == 1){
$a = $a / 10;
$b = $b / 10;
}
if ($decimal_selector == 2){
$a = $a / 10;
$b = $b / 100;
}
if ($decimal_selector == 3){
$a = $a / 100;
$b = $b / 10;
}
if ($decimal_selector == 4){
$a = $a / 100;
$b = $b / 100;
}
if ($decimal_selector == 5){
$a = $a / 1000;
$b = $b / 1000;
}
if ($decimal_selector == 6){
$a = $a / 1000;
$b = $b / 100;
}
if($b < $a){
$b = $b + ($a - $b) + $adjuster;
}
$c = $b - $a;
if(intval($c) == $c) {
$c_is_int = 1;
} else {
$c_is_int = 0;
}
echo intval($c) . '<br>';
echo $c_is_int . '<br>';
echo $c . '<br><br>';
} while($c_is_int == 1);
A double subtracting a double results in a double, even if that number is a whole number
$c = (int) ($b - $a);
Do something like this to see if $c is a whole number (possibly stored as a double):
if(intval($c) == $c) {
echo "I'm a whole number";
}
See here: http://3v4l.org/ubPK4