Recently I needed to determine the size of N is unknown, only the state of N is known. May seem like a weird thing to need, but a example is finding the maximum size of sending email to a SMTP server when the maximum size is currently unknown. You can send $size email each iteration and the direction will be TRUE if the email is to big and is rejected by the server, or FALSE if the email is accepted.
Below is a example.
// our arbitrary number that if not being used in this example, would be
// otherwise unknown
$n = 1;
echo "Finding: $n\n";
$direction = FALSE;
$step = 1;
$size = $sizeLeast = $sizeMax = $i = 0;
while(1) {
// small var for counting, could be taken out if you don't care how many
// iterations it took (in common use you wouldn't)
$i++;
// this should be a function call or something that says what the current
// state of N is, above (true) or below (false), here $n is just a arbitrary
// number and to determine the state we compare it against current $size
$direction = ($size > $n);
// simple steps based on the current state of n (direction), the call could
// be here instead of assigning direction for more performance
if($direction) {
$sizeMax = $size;
$step = (int) round($step/2);
$size -= $step;
} else {
$sizeLeast = $size;
$step = $step*2;
$size += $step;
}
// if sizemax - sizeleast is 1, then obviously the size is sizeLeast
if(1 === ($sizeMax - $sizeLeast) && 1 === $step) {
break;
}
}
echo "Found: $size in $i iterations\n";
Matematikai függvények
Bevezetés
Ezek a matematikai függvények csak a gépeden ábrázolható integer és float típusok értéktartományába eső értékeket képes kezelni (ez jelenleg azonos a C beli long és double típusokéval). Ha nagyobb számokat kell kezelni, akkor a nézd meg a BCMath tetszőleges pontosságú matematikai függvényeket..
Lásd még a kézikönyv aritmetikai operátorok oldalát!
Követelmények
Az itt leírt függvények használatához semmilyen külső függvénykönyvtár megléte nem szükségeltetik.
Telepítés
Semmilyen telepítés nem szükséges ezen függvények használatához, a PHP alapelemei.
Futásidejű beállítások
Ez a kiterjesztés semmilyen konfigurációs beállításokat nem definiál a php.ini állományban.
Erőforrás típusok
Ez a kiterjesztés semmilyen erőforrás típust nem definiál.
Előre definiált állandók
Az itt felsorolt konstansok mindig elérthetőek, mivel részei a PHP alaptelepítésének.
| Állandó | Érték | Leírás |
|---|---|---|
| M_PI | 3.14159265358979323846 | Pi |
| M_E | 2.7182818284590452354 | e |
| M_LOG2E | 1.4426950408889634074 | log_2 e |
| M_LOG10E | 0.43429448190325182765 | log_10 e |
| M_LN2 | 0.69314718055994530942 | log_e 2 |
| M_LN10 | 2.30258509299404568402 | log_e 10 |
| M_PI_2 | 1.57079632679489661923 | pi/2 |
| M_PI_4 | 0.78539816339744830962 | pi/4 |
| M_1_PI | 0.31830988618379067154 | 1/pi |
| M_2_PI | 0.63661977236758134308 | 2/pi |
| M_SQRTPI | 1.77245385090551602729 | sqrt(pi) [4.0.2] |
| M_2_SQRTPI | 1.12837916709551257390 | 2/sqrt(pi) |
| M_SQRT2 | 1.41421356237309504880 | sqrt(2) |
| M_SQRT3 | 1.73205080756887729352 | sqrt(3) [4.0.2] |
| M_SQRT1_2 | 0.70710678118654752440 | 1/sqrt(2) |
| M_LNPI | 1.14472988584940017414 | log_e(pi) [4.0.2] |
| M_EULER | 0.57721566490153286061 | Euler constant [4.0.2] |
Table of Contents
- abs — abszolút érték
- acos — arkusz koszinusz
- acosh — area hiperbolikus koszinusz
- asin — arkusz szinusz
- asinh — area hiperbolikus szinusz
- atan2 — Két változó arkusz tangense
- atan — arkusz tangens
- atanh — area hiperbolikus tangens
- base_convert — tetszőleges számrendszerbe vált át egy számot
- bindec — binárisból tizes számrendszerbe vált át
- ceil — Törtrésszel bíró számot felfelé kerekíti
- cos — Koszinusz
- cosh — Hiperbolikus koszinusz
- decbin — tízes számrendszerből kettesbe vált át
- dechex — tízes számrendszerből tizenhatosba vált át
- decoct — tízes számrendszerből nyolcasba vált át
- deg2rad — fokból radiánba vált át
- exp — e a(z) ... -re emelve
- expm1 — exp(number) - 1 pontos értéke, még ha a number 0-hoz közeli értékű is
- floor — lefelé kerekíti a törtrésszel bíró számot
- fmod — Returns the floating point remainder (modulo) of the division of the arguments
- getrandmax — a legnagyobb lehetséges véletlen számot adja vissza
- hexdec — tizenhatos számrendszerből tízesbe vált át
- hypot — A kér megadott szám négyzetei összegének gyökét adja vissza
- is_finite — Megállapítja egy lebegőpontos számról, hogy az véges-e
- is_infinite — Description
- is_nan — Leírás
- lcg_value — Kombinált lineáris kongruencia generátor
- log10 — tízes alapú logaritmus
- log1p — log(1 + number) pontos értékét adja vissza, akkor is ha a paraméter értéke 0-hoz közeli
- log — természetes alapú logaritmus
- max — megkeresi a legnagyobb értéket
- min — megkeresi a legkisebb értéket
- mt_getrandmax — visszaadja a lehetséges legnagyobb véletlenszámot
- mt_rand — véletlenszámot generál - jobban :)
- mt_srand — beállítja a "jobbik" véletlenszám generátor kiinduló értékét
- octdec — nyolcas számrendszerből tízesbe vált át
- pi — visszaadja pi értékét
- pow — hatványozás
- rad2deg — Radiánból fokokra vált
- rand — véletlenszámot generál
- round — lebegőpontos számot kerekít
- sin — szinusz
- sinh — hiperbolikus szinusz
- sqrt — négyzetgyököt von
- srand — a véletlenszámgenerátor kiinduló értékét állítja be
- tan — tangens
- tanh — hiperbolikus tangens
Matematika
15-Sep-2008 12:27
12-Aug-2008 09:54
If somebody needs to convert a hexal input (i'm NOT talking about hexaDEZIMAl), e.g. a time like
02:30 h
to dezimal, like - in this case -:
2.5
i can recommend this simple function:
<?
function HexalToDezimal ($hexal) {
$dezimal = floor($hexal) + round(($hexal - floor($hexal)) * (1 / 0.6), 2);
return ($dezimal);
}
?>
This can be usefull e.g. if you want to work with unix-timestamps and hexal inputs; e.g. if you want to compute:
time() + [2 houres : 30 minutes]
That is:
time() + (2.5 * 60 * 60)
28-Jul-2008 10:39
<?php
function lcd($n,$m, $maxvarianzpercent=0){
// set $maxvarianzpercent=5 to get a small, but approx. result
/* a better lcd function with varianz:
for example use
lcd(141,180,5) to get the approx. lcd '7/9' which is in fact 140/180
*/
// ATTENTION!!! can be really slow if $m is >1000
$d=$n/$m;
$f=1;
while($d*$f!=intval($d*$f)){
$f++;
}
$r=($d*$f).'/'.$f;
if(($d*$f)<=10 or $f<=10) return $r;
else if($maxvarianzpercent>0){
$f=1;
while($d*$f!=intval($d*$f) and ($d*$f)-intval($d*$f) > $maxvarianzpercent/100){
$f++;
}
return intval($d*$f).'/'.$f;
} else return $r;
}
?>
31-Mar-2008 12:47
// Ordinal one liner tests good up to PHP_INT_MAX-7 on GNU/Linux
function ordinal($n) {
return $n . gmdate("S", (((abs($n) + 9) % 10) + ((abs($n / 10) % 10) == 1) * 10) * 86400);
}
02-Feb-2008 10:24
Wouldn't the following function do the same but a lot easier than the one in the comment before?
function trimInteger($targetNumber,$newLength) {
return $targetNumber%pow(10,$newLength);
}
09-Jan-2008 10:23
//had a mistake in last post, heres the corrected version
/*
Just a simple function to trim digits from the left side of an integer. TRIM DOWN TO 4-> (ie. 987654 => 7654)
*/
function trimInteger($targetNumber,$newLength) {
$digits = pow(10,$newLength);
$s = ($targetNumber/ $digits); //make the last X digits the decimal part
$t = floor($targetNumber / $digits); //drop the last X digits (the decimal part)
$h = $s - $t; //remove all but the decimal part
$newInteger = ($h*$digits); //make the everything after the decimal point the new number
return $newInteger;
}
05-Sep-2007 01:25
Tim's fix of Evan's ordinal function causes another problem, it no longer works for number above 100. (E.g. it returns 111st instead of 111th).
Here is a further modified version which should work for all numbers.
<?PHP
function ordinal($cardinal) {
$cardinal = (int)$cardinal;
$digit = substr($cardinal, -1, 1);
if ($cardinal <100) $tens = round($cardinal/10);
else $tens = substr($cardinal, -2, 1);
if($tens == 1) {
return $cardinal.'th';
}
switch($digit) {
case 1:
return $cardinal.'st';
case 2:
return $cardinal.'nd';
case 3:
return $cardinal.'rd';
default:
return $cardinal.'th';
}
}
?>
Here is another way of calculating the nth term of the Fibonacci sequence, based on Binet's formula (see http://en.wikipedia.org/wiki/Fibonacci_series#Closed_form_expression for more information on this).
In this example, it would display the 17th term of the Fibonacci sequence.
<?php
$n = 17; // Sets a value for $n, the nth term
$phi = (1 + sqrt(5)) / 2; // Sets the value of phi for use in the formula
$u = (pow($phi, $n) - pow(1 - $phi, $n)) / sqrt(5);
echo "U<sub>$n</sub> = $u";
?>
Here is a script that lists the Fibonacci sequence from whatever two terms you specify, in this example from the 12th term to the 27th term (inclusive).
<?php
$f = 12; // Sets the 'f'th term, the term from which to start listing
$t = 27; //Sets the 't'th term, the term at which to stop listing
$phi = (1 + sqrt(5)) / 2; // Sets the value of phi for use in the formula
while($f <= $t) {
$u = (pow($phi, $f) - pow(1 - $phi, $f)) / sqrt(5);
echo "U<sub>$f</sub> = $u<br>\n";
$f++;
}
?>
02-Dec-2006 12:14
Here's a least common denominator (lcd) function:
$array = array(3,4,6,8,18,2);
function lcd($array,$x) {
$mod_sum = 0;
for($int=1;$int < count($array);$int++) {
$modulus[$int] = ($array[0]*$x) % ($array[$int]);
$mod_sum = $mod_sum + $modulus[$int];
}
if (!$mod_sum) {
echo "LCD: ".($array[0]*$x)."\n";
}
else {
lcd($array,$x+1);
}
}
lcd($array,1);
06-Nov-2006 04:36
To add to what Cornelius had, I have written a function that will take an array of numbers and return the least common multiple of them:
function lcm_arr($items){
//Input: An Array of numbers
//Output: The LCM of the numbers
while(2 <= count($items)){
array_push($items, lcm(array_shift($items), array_shift($items)));
}
return reset($items);
}
//His Code below with $'s added for vars
function gcd($n, $m) {
$n=abs($n); $m=abs($m);
if ($n==0 and $m==0)
return 1; //avoid infinite recursion
if ($n==$m and $n>=1)
return $n;
return $m<$n?gcd($n-$m,$n):gcd($n,$m-$n);
}
function lcm($n, $m) {
return $m * ($n/gcd($n,$m));
}
27-Oct-2006 08:51
In Evan's ordinal function, the line:
<?php
$tens = substr($cardinal, -2, 1);
?>
needs to be replaced by:
<?php
$tens = round($cardinal/10);
?>
or similar. At least on PHP 4.3.10, substr("1", -2, 1) returns '1' - so Evan's function gives "1th", as well as "11th". This is contrary to the documentation, but is noted in the comments on the substr manual page.
26-Jul-2006 02:42
A slightly more complex but much more accurate cardinal=>ordinal function (the one below doesn't account for 11th, 12th, and 13th, which don't follow the usual rules):
<?php
function ordinal($cardinal)
{
$cardinal = (int)$cardinal;
$digit = substr($cardinal, -1, 1);
$tens = substr($cardinal, -2, 1);
if($tens == 1)
{
return $cardinal.'th';
}
switch($digit)
{
case 1:
return $cardinal.'st';
case 2:
return $cardinal.'nd';
case 3:
return $cardinal.'rd';
default:
return $cardinal.'th';
}
}
?>
19-Jul-2006 09:24
well just a note.. maybe i'm a bit stupid.. but remember to use pow() rather than the "^" sign for exponents.. as it took me 5 minutes to figure out why it wasn't working.
12-Jul-2006 06:10
Here is another payment function with working future value($fv) option:
function payment($r,$np,$pv,$fv,$prec) {
/* Calculates the monthly payment
** $apr = the annual percentage rate of the loan.
** $n = number of monthly payments (360 for a 30year loan)
** $pv = present value or principal of the loan
** $fv = future value of the loan (after payments)
** $prec = the precision you wish rounded to
*/
/****************************************\
** No Warranty is expressed or implied. **
*****************************************/
if(!$fv) $fv = 0;
$mypmt=$r * (-$fv+pow((1+$r),$np)*$pv)/(-1+pow((1+$r),$np));
return round($mypmt, $prec);
}
07-Jul-2006 12:07
@ Moikboy:
This may or may not be more simplified factorialization:
<?php
$f=$fact=25;
while ($fact>0)
{$f=$f*$fact--;}
echo $f;
?>
08-Jun-2006 08:23
I could not resist to do a simpler version of the ordinal function:
<?php
function ordinal($num)
{
$num = (int)$num;
$digit = substr($num, -1, 1);
$ord = "th";
switch($digit)
{
case 1: $ord = "st"; break;
case 2: $ord = "nd"; break;
case 3: $ord = "rd"; break;
break;
}
return $num.$ord;
}
?>
One could replace the typecast with
<?php
if($num===NULL or $num==="")
{return NULL;}
?>
to get an empty result instead of "0th" in case $num is empty too.
10-May-2006 04:15
I think, this is the optimal code for calculating factorials:
<?php
function fact($int){
if($int<2)return 1;
for($f=2;$int-1>1;$f*=$int--);
return $f;
};
?>
And another one for calculating the $int-th Fibonacci-number:
<?php
function fib($int){
static $fibTable=array();
return empty($fibTable[$int])?$fibTable[$int] = $int>1?fib($int-2)+fib($int-1):1:$fibTable[$int];
};
?>
21-Mar-2006 05:48
Just a simple function to find the ordinal ending to any number if you're printing for example: "The nth result is..."
function ordinal($num) {
$digit = substr($num,-1,1);
$ord = array(
0 => 'th',
1 => 'st',
2 => 'nd',
3 => 'rd',
4 => 'th',
5 => 'th',
6 => 'th',
7 => 'th',
8 => 'th',
9 => 'th'
);
$string = $num.$ord[$digit];
return $string;
}
03-Mar-2006 04:36
A function that simulates the sum operator. (http://en.wikipedia.org/wiki/Sum). Be careful with the expression because it may cause a security hole; note the single quotes to don't parse the "$".
<?php
# @param string $expr expression to evaluate (for example (2*$x)^2+1)
# @param string $var dummy variable (for example "x")
# @param integer $start
# @param integer $end
# @param integer $step
function sum($expr,$var,$start,$end,$step = 1) {
$expr = str_replace(';','',$expr);
$var = str_replace('$','',$var);
$start = (int)$start; $end = (int)$end; $step = (int)$step; $sum = 0;
for ($i = $start; $i <= $end; $i = $i + $step) {
$_expr = str_replace('$'.$var,$i,$expr);
$_eval = '$_result = '.$_expr.'; return $_result;';
$_result = eval($_eval);
if($result === FALSE) return "SYNTAX ERROR : $expr";
$sum += $_result;
}
return (int)$sum;
}
?>
17-Feb-2006 04:39
Thanks to Chronial "at" cyberpunkuniverse.de, I was able to create the binompdf(n, p, k) function.
<?php
function nCr($n, $k){
if ($k > $n)
return NaN;
if (($n - $k) < $k)
return nCr($n, ($n - $k));
$return = 1;
for ($i=0; $i<$k; $i++){
$return *= ($n - $i) / ($i + 1);
}
return $return;
}
function binompdf($n, $p, $k){
$return = nCr($n, $k) * pow($p, $k) * pow((1 - $p), ($n - $k));
return $return;
}
?>
01-Feb-2006 06:16
I needed to approximate an integral because i was not able to calculate it, so i wrote this function. It approximates an integral with the composite Simpson's rule.
More information on Simpson's rule: http://en.wikipedia.org/wiki/Simpson%27s_rule
<?php
function simpsonf($x){
// returns f(x) for integral approximation with composite Simpson's rule
return(pow((1+pow($x, (-4))), 0.5));
}
function simpsonsrule($a, $b, $n){
// approximates integral_a_b f(x) dx with composite Simpson's rule with $n intervals
// $n has to be an even number
// f(x) is defined in "function simpsonf($x)"
if($n%2==0){
$h=($b-$a)/$n;
$S=simpsonf($a)+simpsonf($b);
$i=1;
while($i <= ($n-1)){
$xi=$a+$h*$i;
if($i%2==0){
$S=$S+2*simpsonf($xi);
}
else{
$S=$S+4*simpsonf($xi);
}
$i++;
}
return($h/3*$S);
}
else{
return('$n has to be an even number');
}
}
?>
01-Dec-2005 01:01
If you're an aviator and needs to calculate windcorrection angles and groundspeed (e.g. during flightplanning) this can be very useful.
$windcorrection = rad2deg(asin((($windspeed * (sin(deg2rad($tt - ($winddirection-180))))/$tas))));
$groundspeed = $tas*cos(deg2rad($windcorrection)) + $windspeed*cos(deg2rad($tt-($winddirection-180)));
You can probably write these lines more beautiful, but they work!
26-Oct-2005 05:27
Under some circumstances, it is appropriate to round floats to a given number of significant digits. This function will do it for you:
/**
* Round to significant digits
*
* @param float $f The number to be rounded
* @param integer $n Number of significant digits
*/
function round_significant($f, $n)
{
if ($f==0) return $f;
return round($f, $n-floor(log10(abs($f)))-1);
}
18-Oct-2005 09:37
This is an efficient method of calculating the binomial coefficient C(n,k). This code was derived from Owant: Mastering Algorithms with Perl.
<?php
// calculate binomial coefficient
function binomial_coeff($n, $k) {
$j = $res = 1;
if($k < 0 || $k > $n)
return 0;
if(($n - $k) < $k)
$k = $n - $k;
while($j <= $k) {
$res *= $n--;
$res /= $j++;
}
return $res;
}
?>
If you compiled php with --enable-bcmath, you can get full integer values of extremely large numbers by replacing:
$res *= $n--;
$res /= $j++;
with:
$res = bcmul($res, $n--);
$res = bcdiv($res, $j++);
26-Jul-2005 10:50
Median:
number median ( number arg1, number arg2 [, number ...] )
number median ( array numbers )
<?php
function median()
{
$args = func_get_args();
switch(func_num_args())
{
case 0:
trigger_error('median() requires at least one parameter',E_USER_WARNING);
return false;
break;
case 1:
$args = array_pop($args);
// fallthrough
default:
if(!is_array($args)) {
trigger_error('median() requires a list of numbers to operate on or an array of numbers',E_USER_NOTICE);
return false;
}
sort($args);
$n = count($args);
$h = intval($n / 2);
if($n % 2 == 0) {
$median = ($args[$h] + $args[$h-1]) / 2;
} else {
$median = $args[$h];
}
break;
}
return $median;
}
?>
26-Jul-2005 07:57
thearbitcouncil at gmail dot com, you could just use array_sum():
<?php
function average($arr)
{
if (!is_array($arr)) return false;
return array_sum($arr)/count($arr);
}
$array = array(5, 10, 15);
echo average($array); // 10
?>
01-Jun-2005 03:48
If you're really concerned about speed, you could compute the factorial of large numbers using the Gamma function of n-1.
Integral y^(t-1)*Exp(-y) for y from 0 to Infinity
For Fibonacci numbers, there's a better-than-recursive way.
((1+sqrt(5))/2)^(n/sqrt(5)) - ((1-sqrt(5))/2)^(n/sqrt(5))
10-Mar-2005 11:41
For all you guys writing mortgage calculators out there:
<?php
function payment($apr,$n,$pv,$fv=0.0,$prec=2){
/* Calculates the monthly payment rouned to the nearest penny
** $apr = the annual percentage rate of the loan.
** $n = number of monthly payments (360 for a 30year loan)
** $pv = present value or principal of the loan
** $fv = future value of the loan
** $prec = the precision you wish rounded to
*/
/****************************************\
** No Warranty is expressed or implied. **
*****************************************/
if ($apr !=0) {
$alpha = 1/(1+$apr/12);
$retval = round($pv * (1 - $alpha) / $alpha /
(1 - pow($alpha,$n)),$prec) ;
} else {
$retval = round($pv / $n, $prec);
}
return($retval);
}
?>
19-Feb-2005 03:42
while joogat's one line function is short, it is probably better to calculate factorial iteratively instead of recursively. keep in mind if you want large factorials, you'll need to use some sort of arbitrary precision integer or perhaps the BCMath functions. then again, unless you're trying to do large numbers (170! is the highest that you can do that does not return infinity) you probably won't notice any time difference.
<?php
function factorial($in) {
// 0! = 1! = 1
$out = 1;
// Only if $in is >= 2
for ($i = 2; $i <= $in; $i++) {
$out *= $i;
}
return $out;
}
?>
06-Jan-2005 05:32
Two functions I didn't find elsewhere... one to compute mean of an array of numbers, and another to computer variance of a sample of numbers. Both take an array of numbers as arguments. Not much error checking, or optimization...
(note: variance function uses the average function...)
<?php
function average($arr)
{
if (!count($arr)) return 0;
$sum = 0;
for ($i = 0; $i < count($arr); $i++)
{
$sum += $arr[$i];
}
return $sum / count($arr);
}
function variance($arr)
{
if (!count($arr)) return 0;
$mean = average($arr);
$sos = 0; // Sum of squares
for ($i = 0; $i < count($arr); $i++)
{
$sos += ($arr[$i] - $mean) * ($arr[$i] - $mean);
}
return $sos / (count($arr)-1); // denominator = n-1; i.e. estimating based on sample
// n-1 is also what MS Excel takes by default in the
// VAR function
}
echo variance(array(4,6,23,15,18)); // echoes 64.7...correct value :)
?>
17-Nov-2004 07:34
If you need to deal with polar co-ordinates for somereason you will need to convert to and from x,y for input and output in most situations: here are some functions to convert cartesian to polar and polar to cartesian
<?
//returns array of r, theta in the range of 0-2*pi (in radians)
function rect2polar($x,$y)
{
if(is_numeric($x)&&is_numeric($y))
{
$r=sqrt(pow($x,2)+pow($y,2));
if($x==0)
{
if($y>0) $theta=pi()/2;
else $theta=3*pi()/2;
}
else if($x<0) $theta=atan($y/$x)+pi();
else if($y<0) $theta=atan($y/$x)+2*pi();
else $theta=atan($y/$x);
$polar=array("r"=>$r,"theta"=>$theta);
return $polar;
}
else return false;
}
//r must be in radians, returns array of x,y
function polar2rect($r,$theta)
{
if(is_numeric($r)&&is_numeric($theta))
{
$x=$r*cos($theta);
$y=$r*sin($theta);
$rect=array("x"=>$x,"y"=>$y);
}
else
{
return false;
}
}
?>
25-Sep-2004 12:05
Occasionally a user must enter a number in a form. This function converts fractions to decimals and leaves decimals untouched. Of course, you may wish to round the final output, but that is not included here.
<?php
/*Some example values of $q
$q = "2.5";
$q = "2 1/2";
$q = "5/2";
*/
function Deci_Con($q){
//check for a space, signifying a whole number with a fraction
if(strstr($q, ' ')){
$wa = strrev($q);
$wb = strrev(strstr($wa, ' '));
$whole = true;//this is a whole number
}
//now check the fraction part
if(strstr($q, '/')){
if($whole==true){//if whole number, then remove the whole number and space from the calculations
$q = strstr($q, ' ');
}
$b = str_replace("/","",strstr($q, '/'));//this is the divisor
//isolate the numerator
$c = strrev($q);
$d = strstr($c, '/');
$e = strrev($d);
$a = str_replace("/","",$e);//the pre-final numerator
if($whole==true){//add the whole number to the calculations
$a = $a+($wb*$b);//new numerator is whole number multiplied by denominator plus original numerator
}
$q = $a/$b;//this is now your decimal
return $q;
}else{
return $q;//not a fraction, just return the decimal
}
}?>
16-Sep-2004 08:58
Method to convert an arbitrary decimal number to its most reduced fraction form (so a string is returned, this method would probably be used for output formatting purposes.) There were other methods similar to this one on the page, but none did quite what I wanted. It's maybe not the most elegant code, but it gets the job done. Hope this helps someone. An iterative form of Euclid's algorithm is used to find the GCD.
<?php
function dec2frac( $decimal )
{
$decimal = (string)$decimal;
$num = '';
$den = 1;
$dec = false;
// find least reduced fractional form of number
for( $i = 0, $ix = strlen( $decimal ); $i < $ix; $i++ )
{
// build the denominator as we 'shift' the decimal to the right
if( $dec ) $den *= 10;
// find the decimal place/ build the numberator
if( $decimal{$i} == '.' ) $dec = true;
else $num .= $decimal{$i};
}
$num = (int)$num;
// whole number, just return it
if( $den == 1 ) return $num;
$num2 = $num;
$den2 = $den;
$rem = 1;
// Euclid's Algorithm (to find the gcd)
while( $num2 % $den2 ) {
$rem = $num2 % $den2;
$num2 = $den2;
$den2 = $rem;
}
if( $den2 != $den ) $rem = $den2;
// now $rem holds the gcd of the numerator and denominator of our fraction
return ($num / $rem ) . "/" . ($den / $rem);
}
?>
Examples:
echo dec2frac( 10 );
echo dec2frac( .5 );
echo dec2frac( 5.25 );
echo dec2frac( .333333333 );
yields:
10
1/2
21/4
333333333/1000000000
08-Jun-2004 10:36
For people interest in Differential Equations, I've done a function that receive a string like: x^2+x^3 and put it in
2x+3x^2 witch is the differantial of the previous equation.
In the code there is one thing missing: the $string{$i} is often going outOfBound (Uninitialized string offset: 6 in...)
if your error setting is set a little too high... I just dont know how to fix this.
So there is the code for differential equation with (+ and -) only:
<?
function differentiel($equa)
{
$equa = strtolower($equa);
echo "Equation de depart: ".$equa."<br>";
$final = "";
for($i = 0; $i < strlen($equa); $i++)
{
//Make a new string from the receive $equa
if($equa{$i} == "x" && $equa{$i+1} == "^")
{
$final .= $equa{$i+2};
$final .= "x^";
$final .= $equa{$i+2}-1;
}
elseif($equa{$i} == "+" || $equa{$i} == "-")
{
$final .= $equa{$i};
}
elseif(is_numeric($equa{$i}) && $i == 0)
{
//gerer parenthese et autre terme generaux + gerer ^apres: 2^2
$final .= $equa{$i}."*";
}
elseif(is_numeric($equa{$i}) && $i > 0 && $equa{$i-1} != "^")
{
//gerer ^apres: 2^2
$final .= $equa{$i}."*";
}
elseif($equa{$i} == "^")
{
continue;
}
elseif(is_numeric($equa{$i}) && $equa{$i-1} == "^")
{
continue;
}
else
{
if($equa{$i} == "x")
{
$final .= 1;
}
else
{
$final .= $equa{$i};
}
}
}
//
//Manage multiplication add in the previous string $final
//
$finalMul = "";
for($i = 0; $i < strlen($final); $i++)
{
if(is_numeric($final{$i}) && $final{$i+1} == "*" && is_numeric($final{$i+2}))
{
$finalMul .= $final{$i}*$final{$i+2};
}
elseif($final{$i} == "*")
{
continue;
}
elseif(is_numeric($final{$i}) && $final{$i+1} != "*" && $final{$i-1} == "*")
{
continue;
}
else
{
$finalMul .= $final{$i};
}
}
echo "equa final: ".$finalMul;
}
?>
I know this is not optimal but i've done this quick :)
If you guys have any comment just email me.
I also want to do this fonction In C to add to phpCore maybe soon...
Patoff
26-May-2004 10:04
The fastest O(1) factorial function has a lookup table of all the factorials that fit within the output range. With an array of the first 34 (float) or 170 (double) factorials, you get identical results in a fraction of the time.
26-May-2004 04:32
Here is my factorial function which i think is very simple and without any confusion. email me comments if you like if i had something wrong.
<?php
function factorial($number)
{
$temp = 1;
while ($number > 1){
$temp *= $number--;
}
return $temp;
}
