Implement an ERF function in PHP - php

I want to implement an ERF function in PHP. I got its formula from wikipedia
P_Value = 1- ( ERF ( ABS ( Residual –mean ) )/(√2*SD )
I didn't get the idea how to implement it in PHP.

Based on the formula you provided, only the ERF (Error function) part should look like this:
function ERF ($difference) {
return abs($difference);
}
Now call $value = ERF($residual - $mean); from anywhere inside a php script to store the ERF value in the $value variable.
Edit:
Let's assume you meant this formula:
So, it should be:
function ERF ($ll, $ul, $t, $dt, $dx) {
$val = 0;
for($i = $ll; $i <= $ul; $i+=$dx){
$val += exp(-pow($t,2)) * $dt;
}
return (2/sqrt(pi())) * $val;
}
now call, $value = ERF(0, $x, $t, $dt, $dx); where $x is the upper limit, $t is the time and $dt is the dt part of integration as in time interval.
Note: I've added another parameter $dx here because it is an integral for continuous domain and $dx, $dt both should be very close to 0 for better approximations. For discrete values, you can provide both $dx and $dt as 1. And that would rather be called summation than integral.
For better approximation on integration, see Numerical integration algorithms and techniques.

There are better ways to approximate the error function than by naive numerical integration. The Wikipedia article about erf has a formula for numerical approximation. You can probably find others in Abramowitz & Stegun "Handbook of Mathematical Functions" or maybe the Digital Library of Mathematical Functions.
I found an implementation in PHP here: http://php.net/manual/en/function.stats-stat-percentile.php (look for the term "error function" in the text). Not sure which formula this implements.

Related

Pearson Correlation returns 0 on exact matchs

I am using this PHP routine to calc Pearson Correlation:
function correlation ($x,$y) {
$length = count($x);
$mean1 = array_sum($x)/$length;
$mean2 = array_sum($y)/$length;
$a = $b = 0;
$a2 = $b2 = 0;
$axb = 0;
for ($i = 0; $i < $length; $i++) {
$a = $x[$i]-$mean1;
$b = $y[$i]-$mean2;
$axb +=$a*$b;
$a2 += pow($a,2);
$b2 += pow($b,2);
}
if ($sqrt = sqrt($a2*$b2))
return $axb/$sqrt;
return 0;
}
When I test it for several conditions it returns 0 on exact matchs:
echo correlation([0,0,0,0,0],[0,0,0,0,0]); // Returns 0!!
echo correlation([0,0,0,0,0],[1,1,1,1,1]); // Returns 0!!
echo correlation([1,1,1,1,1],[1,1,1,1,1]); // Returns 0!!
echo correlation([0,0,0,0,0],[9,9,9,9,9]); // Returns 0!!
echo correlation([0,0,0,0,0],[0,1,2,3,4]); // Returns 0 OK
echo correlation([9,9,9,9,9],[0,1,2,3,4]); // Returns 0 OK
echo correlation([0,1,2,3,4],[0,1,2,3,4]); // Returns 1 OK
Why? and How to accomplish that? Thank you!
For info:
A Pearson correlation is a number between -1 and 1 that indicates the
extent to which two variables are linearly related. The Pearson
correlation is also known as the “product moment correlation
coefficient” (PMCC) or simply “correlation”.
Approach 1 (doing at your own):
Using PHP to statistics is a hard path.
First of all, as you're using a weak typed language (you don't need to specify the types on variables), the language can interpret as int so, you need to set all of your variables on type float and execute again to run this. You can have some problems with float in PHP, see here why I talking this: https://3v4l.org/1FU9J
But if you don't mind about high precision, you can modify your precision you can set your round() function or you can set ini_set('precision', 3); to get the precision on your data.
Another thing. If you need precision, you need to use bc extension because floating point in PHP is a problem and can affect your results.
Look more about bc math extension here: https://www.php.net/manual/en/book.bc.php or try to use another language.
Some references about the floating point:
https://www.leaseweb.com/labs/2013/06/the-php-floating-point-precision-is-wrong-by-default/
Problem with Floats! (in PHP)
Approach 2 (using language functions):
And, PHP have some functions to help in this. So, if this isn't a homework to learn or something like this, you can try this: https://www.php.net/manual/en/function.stats-stat-correlation.php

Does a "clamp" number function exist in PHP?

I wrote a function to "clamp" numbers in PHP, but I wonder if this function exists natively in the language.
I read PHP.net documentation in the math section, but I couldn't find it.
Basically what my function does is that it accepts a variable, an array of possible values, and a default value, this is my function's signature:
function clamp_number($value, $possible_values, $default_value)
If $value does not match any of the $possible_values then it defaults to $default_value
I think my function would be way faster if PHP already provides it natively because I'm using quite often in my program.
It seems as though you are just trying to find a number within a set. An actual clamp function will make sure a number is within 2 numbers (a lower bounds and upper bounds). So psudo code would be clamp(55, 1, 10) would produce 10 and clamp(-15, 1, 10) would produce 1 where clamp(7, 1, 10) would produce 7. I know you are looking for more of an in_array method but for those who get here from Google, here is how you can clamp in PHP without making a function (or by making this into a function).
max($min, min($max, $current))
For example:
$min = 1;
$max = 10;
$current = 55;
$clamped = max($min, min($max, $current));
// $clamped is now == 10
A simple clamp method would be:
function clamp($current, $min, $max) {
return max($min, min($max, $current));
}
$value = in_array($value, $possible_values) ? $value : $default_value;
I think is worth to know that...
https://wiki.php.net/rfc/clamp
Is approved and will exist in the core

Cheating PHP integers

This is in relation to my post here but taken in a completely different direction
Charset detection in PHP
essentially, i'm looking to reduce the memory that many huge arrays cause.
These arrays are just full of integers but seeing as PHP uses 32bit and 64 bit integers internally (depending which version you have compiled for your CPU type), it eats the memory.
is there a way to cheat PHP into using 8bit or 16bit integers?
I've thought about using pack(); to accomplish this so I can have an array of packed binary values and just unpack them as I need them (yes I know this would make it slower but is much faster than the alternative of loading and then running through each array individually as you can stream the text through so they all need to be in memory at the same time to keep speed up)
can you suggest any better alternatives to accomplish this? i know it's very hacky but I need to prevent huge memory surges.
Don't tell nobody!
class IntegerstringArray IMPLEMENTS ArrayAccess {
var $evil = "0000111122220000ffff";
// 16 bit each
function offsetExists ( $offset ) {
return (strlen($this->evil) / 4) - 1 >= $offset;
}
function offsetGet ( $offset ) {
return hexdec(substr($this->evil, $offset * 4, 4));
}
function offsetSet ( $offset , $value ) {
$hex = dechex($value);
if ($fill = 4 - strlen($hex)) {
$hex = str_repeat("0", $fill) . $hex;
}
for ($i=0; $i<4; $i++) {
$this->evil[$offset*4+$i] = $hex[$i];
}
}
function offsetUnset ( $offset ) {
assert(false);
}
}
So you can pretty much create an array object from this:
$array = new IntegerstringArray();
$array[2] = 65535;
print $array[2];
It internally stores a list and accepts 16-bit integers. The array offsets must be consecutive.
Not tested. Just as an implementation guide.

How to get a random value from 1~N but excluding several specific values in PHP?

rand(1,N) but excluding array(a,b,c,..),
is there already a built-in function that I don't know or do I have to implement it myself(how?) ?
UPDATE
The qualified solution should have gold performance whether the size of the excluded array is big or not.
No built-in function, but you could do this:
function randWithout($from, $to, array $exceptions) {
sort($exceptions); // lets us use break; in the foreach reliably
$number = rand($from, $to - count($exceptions)); // or mt_rand()
foreach ($exceptions as $exception) {
if ($number >= $exception) {
$number++; // make up for the gap
} else /*if ($number < $exception)*/ {
break;
}
}
return $number;
}
That's off the top of my head, so it could use polishing - but at least you can't end up in an infinite-loop scenario, even hypothetically.
Note: The function breaks if $exceptions exhausts your range - e.g. calling randWithout(1, 2, array(1,2)) or randWithout(1, 2, array(0,1,2,3)) will not yield anything sensible (obviously), but in that case, the returned number will be outside the $from-$to range, so it's easy to catch.
If $exceptions is guaranteed to be sorted already, sort($exceptions); can be removed.
Eye-candy: Somewhat minimalistic visualisation of the algorithm.
I don't think there's such a function built-in ; you'll probably have to code it yourself.
To code this, you have two solutions :
Use a loop, to call rand() or mt_rand() until it returns a correct value
which means calling rand() several times, in the worst case
but this should work OK if N is big, and you don't have many forbidden values.
Build an array that contains only legal values
And use array_rand to pick one value from it
which will work fine if N is small
Depending on exactly what you need, and why, this approach might be an interesting alternative.
$numbers = array_diff(range(1, N), array(a, b, c));
// Either (not a real answer, but could be useful, depending on your circumstances)
shuffle($numbers); // $numbers is now a randomly-sorted array containing all the numbers that interest you
// Or:
$x = $numbers[array_rand($numbers)]; // $x is now a random number selected from the set of numbers you're interested in
So, if you don't need to generate the set of potential numbers each time, but are generating the set once and then picking a bunch of random number from the same set, this could be a good way to go.
The simplest way...
<?php
function rand_except($min, $max, $excepting = array()) {
$num = mt_rand($min, $max);
return in_array($num, $excepting) ? rand_except($min, $max, $excepting) : $num;
}
?>
What you need to do is calculate an array of skipped locations so you can pick a random position in a continuous array of length M = N - #of exceptions and easily map it back to the original array with holes. This will require time and space equal to the skipped array. I don't know php from a hole in the ground so forgive the textual semi-psudo code example.
Make a new array Offset[] the same length as the Exceptions array.
in Offset[i] store the first index in the imagined non-holey array that would have skipped i elements in the original array.
Now to pick a random element. Select a random number, r, in 0..M the number of remaining elements.
Find i such that Offset[i] <= r < Offest[i+i] this is easy with a binary search
Return r + i
Now, that is just a sketch you will need to deal with the ends of the arrays and if things are indexed form 0 or 1 and all that jazz. If you are clever you can actually compute the Offset array on the fly from the original, it is a bit less clear that way though.
Maybe its too late for answer, but I found this piece of code somewhere in my mind when trying to get random data from Database based on random ID excluding some number.
$excludedData = array(); // This is your excluded number
$maxVal = $this->db->count_all_results("game_pertanyaan"); // Get the maximum number based on my database
$randomNum = rand(1, $maxVal); // Make first initiation, I think you can put this directly in the while > in_array paramater, seems working as well, it's up to you
while (in_array($randomNum, $excludedData)) {
$randomNum = rand(1, $maxVal);
}
$randomNum; //Your random number excluding some number you choose
This is the fastest & best performance way to do it :
$all = range($Min,$Max);
$diff = array_diff($all,$Exclude);
shuffle($diff );
$data = array_slice($diff,0,$quantity);

Alternative/faster methods of converting an integer to a cartesian coordinate?

As a fun side-project for myself to help in learning yet another PHP MVC framework, I've been writing Reversi / Othello as a PHP & Ajax application, mostly straightforward stuff. I decided against using a multidimensional array for a number of reasons and instead have a linear array ( in this case 64 elements long ) and a couple methods to convert from the coordinates to integers.
So I was curious, is there any other, possibly faster algorithms for converting an integer to a coordinate point?
function int2coord($i){
$x = (int)($i/8);
$y = $i - ($x*8);
return array($x, $y);
}
//Not a surprise but this is .003 MS slower on average
function int2coord_2($i){
$b = base_convert($i, 10, 8);
$x = (int) ($b != 0 ? $b/8 : 0); // could also be $b < 8 for condition
$y = $b % 10;
return array($x, $y);
}
And for posterity sake, the method I wrote for coord2int
function coord2int($x, $y){
return ($x*8)+$y;
}
Update:
So in the land of the weird, the results were not what I was expecting but using a pre-computed lookup table has predominantly shown to be the fastest, guess trading memory for speed is always a winner?
There was a table with times here but I cut it due to styling issues with SO.
Oh yes! This is a perfect example of binary:
function int2coord($i){
$x = $i >> 3;
$y = $i & 0x07;
return array($x, $y);
}
The reality is that a good compiler will find this optimization and use it, so it's not necessarily faster. Test and see if your compiler/interpreter does this.
It works because any binary division by 8 is the same as a right shift by 3 bits. Modern processors have barrel shifters that can do up to a 32 bit shift in one instruction.
The reverse is as easy:
function coord2int($x, $y){
return ($x << 3)+$y;
}
-Adam
I don't have the time to measure this myself right now, but I would suspect that a pre-computed lookup table would beat your solution in speed. The code would look something like this:
class Converter {
private $_table;
function __construct()
{
$this->_table = array();
for ($i=0; $i<64; $i++) {
$this->_table[$i] = array( (int)($i/8), (int)($i%8) );
}
}
function int2coord( $i )
{
return $this->_table[$i];
}
}
$conv = new Converter();
$coord = $conv->int2coord( 42 );
Of course, this does add a lot of over-head so in practice you would only bother to pre-compute all coordinates if you conversion code was called very often.
I'm not in a position to measure right now, but you should be able to eke out some additional speed with this:
function int2coord($i){
$y = $i%8;
$x = (int)($i/8);
return array($x, $y);
}
edit: ignore me -- Adam's bitshifting answer should be superior.
function int2coord_3($i){
return array((int) ($i / 8), ($i % 8));
}
this is a little faster because there is no var declaration and affectation.
I think most of your performance is lost by returning array(...) at the end. Instead, I propose:
* define two functions, one for x and one for y
or
* inline the bit arithmetic in code needing the calculation

Categories