How to produce approximate fraction numbers from irrational number on MatLab? - php

I have a clumsy PHP code that I've used to get approximate fraction numbers for irrational numbers like pi, phi, square root of 2, 3 and so on. I'd like to get a formula that I can use on MatLab and get both data table and draw a plot based on approximate fraction numbers. Maybe someone already can grab from this but I'll provide PHP code to complement the case:
$n = phi(); # irrational number (imaginary/complex number?)
$x = 500; # how many numbers to check
$max = 50; # how many instances to show
$precision = 0.0001;
# check every i against every j and make a comparison how near their values are to each other
for ($i=1; $i<$x; $i++) {
for ($j=1; $j<$x; $j++) {
# compared value is stored on array. very distant numbers needs to be discarded ($precision) or array gets easily too big, limit 64k
if (($d = abs(($n - ($i/$j)))) && $d > $precision) continue;
$c[] = array($i, $j, $d);
}
}
# sort comparison chart by third index (2)
array_qsort($c, 2);
# print max best values from the sorted comparison chart
$count = count($c);
echo "closest fraction numbers for $n from $count calculated values are:<br />\n<br />\n";
$r = 0;
foreach ($c as $abc) {
$r++;
$d = $abc[0]/$abc[1];
echo $abc[0] . '/' . $abc[1] . ' = ' . $d . ' (' . round($abc[2]*(1/$precision), 10) . ')' . "<br />\n";
if ($r > $max) break;
}

There are more efficient algorithms, here is one:
function [a, b, c] = approxfrac( r, precision )
a = floor(r);
r = r - a;
if r==0,
b=0;
c=1;
return
end
p1 = 0; q1 = 1;
p2 = 1; q2 = 1;
b = p1+p2;
c = q1+q2;
while abs(r-b/c) > precision,
if r>b/c,
p1 = b; q1 = c;
else
p2 = b; q2 = c;
end
b = p1+p2;
c = q1+q2;
end
end

There's a function for that: rat

Related

How to print correct multiplication of big number in PHP

I was trying to print multiplication of big numbers and they are resulting in float type scientific number.
var_dump((double)('290287121823'*'290287121823'));
I tried the function number_format and preg_replace to remove all ','. But after number_format the result is not correct.
Used following code:
preg_replace("/,/", "", (number_format(('290287121823'*'290287121823'))));
Output received: 84266613096281242861568
Expected correct output: 84266613096281243382112
The large numbers are computed digits by digits. Like we learn at school (see Long multiplication).
ex:
// 17
// x 27
// ----
// 119
// + 34
// -----
// = 459
Here is a function (which should be optimized) but shows you the principle.
echo bn_mul('17', '27'), PHP_EOL; // 459
echo bn_mul('157', '27'), PHP_EOL; // 4239
echo bn_mul('1234', '6627'), PHP_EOL; // 8177718
echo bn_mul('23958233', '5830'), PHP_EOL; // 139676498390
echo bn_mul('290287121823', '290287121823'), PHP_EOL; // 84266613096281242843329
Implementation:
function bn_mul($n2, $n1) {
$l1 = strlen($n1);
$l2 = strlen($n2);
$rows = [];
for ($idx1 = $l1 - 1 ; $idx1 >= 0 ; $idx1--) {
// get digit
$d1 = substr($n1, $idx1, 1) ;
$carry = 0; // reset carry
$row = []; // store digit of $d1 x each digits of $n2
// prepend 0 (10 * num rows)
for ($x=0 ; $x<count($rows) ; $x++) $row[] = 0;
for ($idx2 = $l2 - 1 ; $idx2 >= 0 ; $idx2--) {
// get digit
$d2 = substr($n2, $idx2, 1) ;
// multiplication of digit 1 x digit 2 + current carry
$r = $d1 * $d2 + $carry;
$carry = 0;
// compute carry
if ($r >= 10) {
$carry = substr($r, 0, -1);
$r = substr($r, -1);
}
$row[] = $r ;
}
if ($carry) $row[] = $carry;
$rows[] = $row ;
}
// Sum digits of rows
$total = [] ;
$carry = 0 ;
for ($x=0;$x < count(end($rows)) ; $x++){
$tot = $carry;
$carry = 0;
foreach ($rows as $row){
if (isset($row[$x])) $tot += $row[$x] ;
}
while ($tot >= 10) {
$tot -= 10;
$carry++;
}
$total[$x] = $tot;
}
return strrev(implode($total));
}
You should keep in mind that even if PHP is NOT typesafe, there are types in the background.
When you look up the documentation you'll find out, that floating points only have a precision up to 14 digits. Therefore, all trailing numbers are "cut off". The magnitude remains and it will print in scientific format but you can't really know what's "below" that 14 digits. Therefore, your try to convert the result is doomed to fail in the first place.
Example:
12345678910111213
^^^ get's cut off

Bailey-Borwein-Plouffe in php trouble

I am trying to implement the BBP algorithm in php. My code is returning a decimal which i thought was odd as it should be in hex. I was told to convert to decimal from hex by multiplying by 16 also but now its all just wrong. Here is a sample:
$n1=$n2=$n3=$n4=$n5=$n6=$n7=$n8 =0;
$S1=$S2=$S3=$S4=$S5=$S6=$S7=$S8 = 0; //initializing
$k = 0;
$m1= 8*$k + 1;
$m2 = 8*$k + 4;
$m3 = 8*$k + 5;
$m4 = 8*$k = 6;
$b =16;
$e=$n-$k;
while($k<$n){ //Sum 1 of 8
$S1 +=Modular($b, $m1, $e)/$m1; //see Moduler_Expansion.php
$k++;
}
$k = $n +1; //redefine for second sum, and every other
while($k<$limit){ //Sum 2 of 8
$S2 += (pow($b,$n-$k))/($m1);
$k++; //now repeat similar process for each sum.
}
and I repeat the process for each term of BBP then:
$S = 4*($S1 + $S2) - 2*($S3+$S4) -($S5+$S6) - ($S7+$S8);
`
Following the wiki page I then strip the integer and multiply by 16, but for $k =0 I get; 3.4977777777778
and for $k = 1: 7.9644444444448.
I dont think these are right, it could just be i do not know how to interpret th ouput properly. Can anyone offer any advice?

PHP: Can array of numbers add up to number

This is more of a puzzle than anything. I've actually found a solution but it is so slow I thought I lost my internet connection (see below).
Here's the problem:
Let's say I have an array of numbers, like so:
$numbers_array = array(1, 2, 3, 4, 5, 6, 7, 8, 9);
Let's also say that I have a number some numbers, stored in variables like so:
$sum = 15;
$sum2 = 24;
$sum3 = 400;
I am trying to create a function that will return true if any of the numbers in $numbers_array can be added together (each only used once) to form the sums:
function is_summable($array_of_nums, $sum_to_check) {
//What to put here?
}
var_dump(is_summable($numbers_array, $sum));
var_dump(is_summable($numbers_array, $sum2));
var_dump(is_summable($numbers_array, $sum3));
The above should output:
bool(true)
bool(true)
bool(false)
Because 7 + 8 = 15, 7 + 8 + 9 = 24, but no combination of 1-9 can create 200.
Here's my EXTREMELY slow solution:
function is_summable($numbers, $sum) {
//Sort provided numbers and assign numerical keys.
asort($numbers);
$numbers = array_values($numbers);
//Var for additions and var for number of provided numbers.
$total = 0;
$numbers_length = count($numbers);
//Empty var to fill below.
$code = '';
//Loop and add for() loops.
for ($i = 0; $i < $numbers_length; $i++) {
$code .= 'for ($n' . $i . ' = 0; $n' . $i . ' < ' . $numbers_length . '; $n' . $i . '++) {';
if ($i != 0) {
$code .= 'if ($n' . $i . ' != $n' . ($i - 1) . ') {';
}
$code .= '$total += intval($numbers[$n' . $i . ']);';
$code .= 'if ($total == $sum) {';
$code .= 'return true;';
$code .= '}';
}
//Add ending bracket for for() loops above.
for ($l = 0; $l < $numbers_length; $l++) {
$code .= '$total -= intval($numbers[$n' . $i . ']);';
if ($l != 0) {
$code .= '}';
}
$code .= '}';
}
//Finally, eval the code.
eval($code);
//If "true" not returned above, return false.
return false;
}
$num_arr = array(1,2,3,4,5,6,7,8,9);
var_dump(is_summable($num_arr, 24));
http://pastebin.com/1nawuwXK
As always, help is appreciated!!
Your problem is in fact a standard algorithmic problem (as Jon mentioned knapsack problem), more specifically Subset sum problem. It can be solved in polynomial time (have look on wiki page).
Pseudocode:
initialize a list S to contain one element 0.
for each i from 1 to N do
let T be a list consisting of xi + y, for all y in S
let U be the union of T and S
sort U
make S empty
let y be the smallest element of U
add y to S
for each element z of U in increasing order do
//trim the list by eliminating numbers close to one another
//and throw out elements greater than s
if y + cs/N < z ≤ s, set y = z and add z to S
if S contains a number between (1 − c)s and s, output yes, otherwise no

How to write a function to determine the population count of a 16-bit integer using php or javascript?

How to write a function to determine the population count of a 16-bit
integer using php or javascript. Population count is defined as the number of bits that are
"turned on," or in others, it is the number of 1s in a binary
representation of a number. For example, the binary number 0b0000 has
a population count of 0 because there aren't any 1 bits. 0b0101 has a
population count of 2, because 2 bits turned on; 0b1110 has a
population count of 3. 0b1111111111111111 has a population count if 16
because there are sixteen 1 bits. Your function should accept an INTEGER
argument and return an INTEGER containing its population count. Example:
f(0) = 0
f(1) = 1
f(2) = 1
f(3) = 2
f(4) = 1
f(5) = 2
Using bitwise and and right shift
function count(n){
c =0;
while(n){
c += n&1;
n = n>>1;
}
return c;
}
The badass way?
var x=0xfffe;
x -= ((x >> 1) & 0x55555555);
x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
x = (((x >> 4) + x) & 0x0f0f0f0f);
x += (x >> 8);
x += (x >> 16);
alert(x & 0x0000003f); //15
Not necessarily badass, but it works...
<?php
$number = 3;
echo "Number: " . $number . "\n";
$bin_number = decbin($number);
$population_count = 0;
echo "Binary String Conversion: " . $bin_number . "\n";
for ($i = strlen($bin_number) - 1; $i >= 0; --$i) {
$population_count += $bin_number[$i];
}
echo "Population Count: " . $population_count . "\n";
?>

Get factors of a number

I need to get two factors ( x, y ) of a given number ( n ) such that:
x * y <= n
x * y should be as close to n as possible
x and y should be as close to each other as possible.
Examples:
n = 16 => x = 4, y = 4
n = 17 => x = 4, y = 4
n = 18 => x = 6, y = 3
n = 20 => x = 5, y = 4
Any language will do but preferably php.
EDIT -- CLARIFICATION
I want to create a rectangle, x units wide * y units tall such that its area is as close to n as possible. x and y must be integers. If n is a prime number then factors of n - 1 are acceptable.
Your specifications weren't quite exact enough. You stated that you wanted factors, yet in your test case 4 is not a factor of 17
The following pseudo code works prioritizing that one factor is exact
for i in range(ceiling(sqrt(n)), 1){
if ( n modulo i ) == 0 {
x = i
y = round(n/i)
}
}
Where as a simple sqrt statement will work for ensuring that the numbers are as close together as possible, but doesn't guarantee that they are factors.
x = y = round( sqrt(n) )
You need to decide how important your three rules are.
Possibility 1: If x * y being as close to n as possible is true then n=17 => 1,17 not 4,4. In this case you want factorisation and there are lots of ways to do it, but code like this is simple:
for(i = floor(sqrt(n)) .. 1) {
if n % i ==0 {
x = i;
y = n/x;
break;
}
}
Possibility 2: If being close to each other is more important you'd expect n=18=>4,4 rather than 3,6, and this code would work. This however is not factors.
x=floor(sqrt(n))
y=floor(n/x)
The problem as written is unsolvable without a clearer specification.
EDIT ------------
Now the spec has been edited it is now defined, but you need to do Possibility 1, see if the result is prime (1 is one of the values) and then if it is repeat doing Possibility 2. However, I doubt this is what whichever teacher wrote this as homework intended.
$num = ...; // some number
if (is_prime($num)) // implement the is_prime() function yourself
--$num; // Subtract to get an even number, which is not a prime
$candidates = array(); // Numbers that may fit.
$top_search = $num / 2; // Limits the useless search for candidates
for($i=1; $i < $top_search; ++$i)
{
if ($num % $i == 0)
$candidates[$i] = $num / $i;
}
// Now, check the array in the middle
An idea from me (more pseudo then php)
$root = sqrt($inputNumber);
$x = floor($root);
$y = floor($root);
if(($root - $x) > 0.5) $y++;
I'd have all the factors written to an array using the following code.
#Application lists all factors/divisors for a number.
targetNumber=input('What number do you want the factors for?\n> ')
factors=[]
for i in range(1,targetNumber):
if targetNumber%i==0:
factors.append(i)
elif targetNumber/i==1:
factors.append(targetNumber)
break
print factors
Then I'd loop through the array to check which ones can actually be used. For more on this algorithm, check out http://pyfon.blogspot.com.au/2012/09/list-factors-of-number-in-python.html
Here is a PHP function that prioritize the two 'factors' being close to each other over having exact factors:
function weird_factors($ori) {
$sq = intval(sqrt($ori));
$start = $sq - 10;
$end = $sq + 10;
$n = 0;
for ($s = $start; $s <= $end; $s++) {
for ($t = $start; $t <= $end; $t++) {
$st = $s * $t;
if ($st <= $ori and $st > $n) {
$n = $st;
$ns = $s;
$nt = $t;
}
}
}
return array($ns, $nt);
}
Write a program to find factor of any number
<?php
if(isset($_POST['sub']))
{ $j=0;
$factor=array();
$num=$_POST['nm1'];
for($i=1;$i<=$num;$i++)
{
if($num%$i==0)
{
$j++;
$factor[$j]=$i;
}
}
}
?>
<table>
<form name="frm" method="post" action="">
<tr> <td>Number:</td> <td><input type="text" name="nm1" /></td> </tr>
<tr><td></td><td><input type="submit" name="sub" /></td>
<td><center><span>
<?php
if(isset($_POST['sub']))
{
echo "Factors are :";for($i=1;$i<=count($factor);$i++)
{ echo $factor[$i].",";
}
}
?>
</span></center></td></tr>
</form>
</table>

Categories