This question already has answers here:
Working with large numbers in PHP
(8 answers)
Closed 2 years ago.
Hello I would like to display in my code a full number to 20 decimal without scientific notation.
I think it's a memory problem in php.
can you help me ? thanks
function get($l, $c)
{
$value = 0;
if (0 <= $c && $c <= $l && $l < 5000) {
$tab = [];
for ($i = 0; $i <= $l; $i++) {
for ($j = 0; $j <= $c; $j++) {
if ($i == $j || $i - 1 <= 0 || $j <= 0) {
$tab[$i][$j] = 1;
$value = $tab[$i][$j];
} elseif ($i != $j) {
$tab[$i][$j] = ($tab[$i - 1][$j - 1]) + ($tab[$i - 1][$j]);
$value = $tab[$i][$j];
}
}
}
}
return $value;
}
echo get(67, 34); // found :1.422652073762E+19 , excpected:14226520737620288370
Have a look at BCMath functions:
function get($l, $c)
{
$value = 0;
if (0 <= $c && $c <= $l && $l < 5000) {
$tab = [];
for ($i = 0; $i <= $l; $i++) {
for ($j = 0; $j <= $c; $j++) {
if ($i == $j || $i - 1 <= 0 || $j <= 0) {
$tab[$i][$j] = 1;
$value = $tab[$i][$j];
} elseif ($i != $j) {
// magic happens here
$tab[$i][$j] = bcadd($tab[$i - 1][$j - 1], $tab[$i - 1][$j]);
$value = $tab[$i][$j];
}
}
}
}
return $value;
}
$result = get(67, 34);
var_dump($result == '14226520737620288370');
echo $result;
Output
bool(true)
14226520737620288370
Working example.
There is that : https://www.php.net/manual/en/function.number-format.php
You can print any number and choose number of decimals you want
Related
I would like to make a program which can calculate first 5000 primary numbers whos ends with 9 :
I tried this but it didn't work :
$div9 = [];
$x = 2;
while (count($div9) <= 5000) {
function findPrime($x)
{
for ($i = 2; $i < ($x / 2); $i++) {
$rest = $x % $i;
if ($rest == 0) {
break;
}
}
return $x;
}
$primeList[] = $x;
for ($j = 0; $j < count($primeList); $j++) {
$array = array_map('intval', str_split($primeList[$j]));
if (end($array[$j]) === 9) {
return $primeList[$j];
$div9[] = $primeList[$j];
}
}
$x++;
}
any hints please?
You should not define a function inside your while loop
This should help
function check_prime($num)
{
if ($num == 1)
return false;
for ($i = 2; $i <= $num/2; $i++)
{
if ($num % $i == 0)
return false;
}
return true;
}
$div9 = [];
$i = 0;
while(count($div9) < 5000) {
if($i%10 === 9 && check_prime($i)) {
$div9[] = $i;
}
$i++;
}
Another variation on the theme, the isPrime function was ported from Javascript cryptoJS library.
# Adapted from CryptoJS v3.1.2
function isPrime( $n=0 ){
$r=sqrt( $n );
for( $f=2; $f <= $r; $f++ ){
if( !( $n % $f ) )return false;
}
return true;
}
function isFactor($n,$f){
return $n % 10 == $f;
}
$limit=5000;
$primes=[];
$x=2;
$f=9;
while( count( $primes ) < $limit ){
if( isPrime( $x ) && isFactor( $x, $f ) )$primes[]=$x;
$x++;
}
printf('<pre>%s</pre>',print_r($primes,true));
I have this gauss_eliminate function, but instead of dealing with real numbers, I want it to work on binary values.
I need the GF2 gauss_eliminate function, where the input is binary and the output is binary.
This produces real values, not binary, eg
0.57142857142857
0.71428571428571
-0.42857142857143
-0.28571428571429
0.14285714285714
Gaussian elimination has these 3 allowed steps:
1) Swapping two rows (for achieving a certain look)
2) Multiplying a row by a nonzero number,
3) Adding a multiple of one row to another row.
-- in GF2: addition operation is XOR : 0+0=0, 0+1=1, 1+0=1, 1+1=0 --and--
multiplication is AND operation: 0*0=0,0*1=0,1*0=0,1*1=1
function gauss_eliminate($A, $b, $N)
{
for ($col = 0; $col < $N; $col++) {
$j = $col;
$max = $A[$j][$j];
for ($i = $col + 1; $i < $N; $i++) {
$tmp = abs($A[$i][$col]);
if ($tmp > $max) {
$j = $i;
$max = $tmp;
}
}
swap_rows($A, $b, $col, $j);
for ($i = $col + 1; $i < $N; $i++) {
$tmp = $A[$i][$col] / $A[$col][$col];
for ($j = $col + 1; $j < $N; $j++) $A[$i][$j] -= $tmp * $A[$col][$j];
$A[$i][$col] = 0;
$b[$i] -= $tmp * $b[$col];
}
}
$x = array();
for ($col = $N - 1; $col >= 0; $col--) {
$tmp = $b[$col];
for ($j = $N - 1; $j > $col; $j--) $tmp -= $x[$j] * $A[$col][$j];
$x[$col] = $tmp / $A[$col][$col];
}
return $x;
}
new code #1, still doesn't work:
function gauss_eliminate($A, $b, $N)
{
for ($col = 0; $col < $N; $col++) {
$j = $col;
$max = $A[$j][$j];
for ($i = $col + 1; $i < $N; $i++) {
$tmp = abs($A[$i][$col]);
if ($tmp > $max) {
$j = $i;
$max = $tmp;
}
}
swap_rows($A, $b, $col, $j);
for ($i = $col + 1; $i < $N; $i++) {
for ($j = $col + 1; $j < $N; $j++)
$A[$i][$j]=( $A[$i][$j] != $A[$col][$j] ) ? 1 : 0;
$A[$i][$col] = 0;
$b[$i]=( $b[$i] != $b[$col] ) ? 1 : 0;
}
}
$x = array();
for ($col = $N - 1; $col >= 0; $col--) {
# $tmp = $b[$col];
# for ($j = $N - 1; $j > $col; $j--) $tmp -= $x[$j] * $A[$col][$j];
$x[$col] = ( $x[$col] != $A[$col][$j] ) ? 1 : 0;
}
return $x;
}
New code #2 - still doesn't work - tmp setup to alternate
function gauss_eliminate($A, $b, $N)
{
for ($col = 0; $col < $N; $col++) {
$j = $col;
$max = $A[$j][$j];
for ($i = $col + 1; $i < $N; $i++) {
$tmp = abs($A[$i][$col]);
if ($tmp > $max) { $j = $i; $max = $tmp; }
}
swap_rows($A, $b, $col, $j);
for ($i = $col + 1; $i < $N; $i++) {
# $tmp = $A[$i][$col] / $A[$col][$col];
for ($j = $col + 1; $j < $N; $j++) $A[$i][$j]=($A[$i][$j] != $A[$col][$j] ? 1 : 0);
$A[$i][$col] = 0;
$b[$i] = ( $b[$i] != $b[$col] ? 1 : 0);
}
}
$x = array();
for ($col = $N - 1; $col >= 0; $col--) {
$tmp = $b[$col];
for ($j = $N - 1; $j > $col; $j--) $tmp = 1 - $tmp;
$x[$col] = ($tmp != $A[$col][$j] ? 1 : 0);
}
return $x;
}
It appears I found the right syntax. I am getting the right result for one example, after modifying the code in a way that makes sense.... converting - to +, and this + to XOR, while / is ignored and * is AND.
Still it would be nice to get a confirmation that this code is correct.
function gauss_eliminate($A, $b, $N) {
for ($col = 0; $col < $N; $col++) {
$j = $col;
$max = $A[$j][$j];
for ($i = $col + 1; $i < $N; $i++) {
$tmp = abs($A[$i][$col]);
if ($tmp > $max) {
$j = $i;
$max = $tmp;
}
}
swap_rows($A, $b, $col, $j);
for ($i = $col + 1; $i < $N; $i++) {
# $tmp = $A[$i][$col] / $A[$col][$col];
# for ($j = $col + 1; $j < $N; $j++) {
# $A[$i][$j] -= $tmp * $A[$col][$j];
# }
# $A[$i][$col] = 0;
# $b[$i] -= $tmp * $b[$col];
$tmp = $A[$i][$col];
for ($j = $col + 1; $j < $N; $j++) {
# $A[$i][$j] = $A[$i][$j] + ( $tmp * $A[$col][$j] );
$A[$i][$j] = ( $A[$i][$j] != ( $tmp && $A[$col][$j] ) ) ? 1 : 0;
}
$A[$i][$col] = 0;
# $b[$i] = $b[$i] + ($tmp * $b[$col]);
$b[$i] = ( $b[$i] != ($tmp && $b[$col]) ) ? 1 : 0;
}
}
$x = array();
for ($col = $N - 1; $col >= 0; $col--) {
$tmp = $b[$col];
for ($j = $N - 1; $j > $col; $j--) {
# $tmp -= $x[$j] * $A[$col][$j];
# $tmp = $tmp + ($x[$j] * $A[$col][$j]);
$tmp = ( $tmp != ($x[$j] && $A[$col][$j]) ) ? 1 : 0;
}
# $x[$col] = $tmp / $A[$col][$col];
$x[$col] = $tmp;
}
return $x;
}
The commented text is the old (non GF2 code) as well as my "middle step" of showing where I convert + to XOR, * to AND, etc
There is Fatal Error in this code:
Call-time pass-by-reference has been removed on line 108. this is
Boyer Moore Algorithm
function suffixes($pattern, &$suffixes)
{
$m = strlen($pattern);
$suffixes[$m - 1] = $m;
$g = $m - 1;
for ($i = $m - 2; $i >= 0; --$i) {
if ($i > $g && $suffixes[$i + $m - 1 - $f] < $i - $g) {
$suffixes[$i] = $suffixes[$i + $m - 1 - $f];
} else {
if ($i < $g) {
$g = $i;
}
$f = $i;
while ($g >= 0 && $pattern[$g] == $pattern[$g + $m - 1 - $f]) {
$g--;
}
$suffixes[$i] = $f - $g;
}
}
}
function badCharacters
function badCharacters($pattern, &$badChars)
{
$m = strlen($pattern);
for ($i = 0; $i < $m - 1; ++$i) {
$badChars[$pattern{$i}] = $m - $i - 1;
}
}
function goodSuffixes
function goodSuffixes($pattern, &$goodSuffixes)
{
$m = strlen($pattern);
$suff = array();
suffixes($pattern, $suff);
for ($i = 0; $i < $m; $i++) {
$goodSuffixes[$i] = $m;
}
for ($i = $m - 1; $i >= 0; $i--) {
if ($suff[$i] == $i + 1) {
for ($j = 0; $j < $m - $i - 1; $j++) {
if ($goodSuffixes[$j] == $m) {
$goodSuffixes[$j] = $m - $i - 1;
}
}
}
}
for ($i = 0; $i < $m - 2; $i++) {
$goodSuffixes[$m - 1 - $suff[$i]] = $m - $i - 1;
}
}
function boyer_moore
function boyer_moore($pattern, $text)
{
$n = strlen($text);
$m = strlen($pattern);
$goodSuffixes = array();
$badCharacters = array();
//this is the line 108
goodSuffixes($pattern, &$goodSuffixes);
badCharacters($pattern, &$badCharacters);
$j = 0;
while ($j < $n - $m) {
for ($i = $m - 1; $i >= 0 && $pattern[$i] == $text[$i + $j]; $i--);
if ($i < 0) {
echo $j;
$j += $goodSuffixes[0];
} else {
$j += max($goodSuffixes[$i], $badCharacters[$text[$i + $j]] - $m + $i + 1);
}
}
}
boyer_moore($pattern, $text);
What is causing this error?
It's clear from the error message:
goodSuffixes($pattern, &$goodSuffixes);
badCharacters($pattern, &$badCharacters);
The '&' is the character that is attempting to pass by reference at calltime. Remove the '&' from in front of the 2 variable names.
goodSuffixes($pattern, $goodSuffixes);
badCharacters($pattern, $badCharacters);
Is it possible to add or concatenate something into a variable name in a PHP variable? For example:
for($g = 7; $g <= 10; $g++){
for($i = 0; $i <= 4; $i++){
$counter = $g - 7;
if($i != $counter){
continue;
} else {
$grade.[$g] = $grades[$i];
}
}
}
I want this to happen:
$grade7 = 0
$grade8 = 1
$grade9 = 2
$grade10 = 3
Concatenates the $g with grade and make this value a variable by adding a $ sign at the starting line...
The example given below:
for($g = 7; $g <= 10; $g++){
for($i = 0; $i <= 4; $i++){
$counter = $g - 7;
if($i != $counter){
continue;
} else {
${"grade".$g} = $grades[$i];
}
}
}
echo $grade7; // 0
echo $grade8; // 1
echo $grade9; // 2
echo $grade10;// 3
One solution would be to create the variables dynamically:
for ($g = 7; $g <= 10; $g++) {
for ($i = 0; $i <= 4; $i++) {
$counter = $g - 7;
if ($i == $counter) {
${'grade' . $g} = $grades[$i];
}
}
}
You should use ARRAY instead of your method. :)
Try to look at variable named like "$$".
EDIT: Maybe something like
var $array = array();
for($g=7; $g<=10; $g++)
{
for($i=0; $i<=4; $i++)
{
$counter = $g - 7;
if($i != $counter) continue;
else $array[$grade.[$g]] = $grades[$i];
}
}
$data = new Array();
for($g = 7; $g <= 10; $g++){
for($i = 0; $i <= 4; $i++){
$counter = $g - 7;
if($i != $counter){
continue;
} else {
$data[$grade.[$g]] = $grades[$i]);
}
}
}
Here is my code:
$n = 300;
$set = 0;
$set2 = 0;
for($i = 1; $i<$n; $i++)
{
for($j = 1; $j <$i; $j++)
{
$qol = $i % $j;
if($qol == 0)
{
$set += $j;
}
}
for($s=1; $s<$set; $s++)
{
$qol2 = $set % $s;
if($s == 0)
{
$set2 += $s;
}
}
if($set2 == $i)
{
echo "$set and $i are amicable numbers</br>";
}
}
I do not know what the heck the problem is!
FYI: 220 and 284 are an example of amicable numbers. The sum of the proper divisors of one number are equal to other number and vice versa (wiki).
I am having troubles following your logic. In your code how would $set2 == $i ever be true? Seems to me that $i would always be greater.
I would do it the following way:
First make a separate function that finds the sums of the proper divisors:
// Function to output sum of proper divisors of $num
function sumDiv($num) {
// Return 0 if $num is 1 or less
if ($num <= 1) {
return 0;
}
$result = 1; // All nums divide by 1
$sqrt = sqrt($num);
// Add divisors to result
for ($i = 2; $i < $sqrt; $i++) {
if ($num % $i == 0) {
$result += $i + $num / $i;
}
}
// If perfect square add squareroot to result
if (floor($sqrt) == $sqrt) {
$result += $sqrt;
}
return $result;
}
Next check each iteration for a match:
$n = 1500;
for ($i = 1; $i < $n; $i++) {
// Get sum of proper devisors of $i, and sum of div. of result.
$currentDivs = sumDiv($i);
$resultDivs = sumDiv($currentDivs);
// Check for a match with sums not equal to each other.
if ($i == $resultDivs && $currentDivs != $resultDivs) {
echo "$i and $currentDivs are amicable numbers<br>";
}
}
Here a functioning phpfiddle.
Warning: Large numbers will take very long to process!