Kansrekening

Status
Niet open voor verdere reacties.

Frats

Terugkerende gebruiker
Lid geworden
22 nov 2008
Berichten
4.492
Hai,

Weet iemand of PHP een ingebouwde kansrekenings library heeft?
Of anders iig een goeie door gebruikers geschreven?

Anders moet ik er zelf een gaan maken, maar dat doe ik liever niet tenzij het echt moet ;)
 
Wat bedoel je precies?

Binomiale verdeling, combinatoriek, normale verdeling etc.?
 
Met name combinatoriek, maar idd dat soort dingen :)
 
Goed aangezien ik niks kon vinden heb ik zelf maar wat geklust.

Mocht iemand er nog wat aan hebben; deze class kan factorizeren en combinaties uitrekenen, en snel ook ;)

Je kunt em hier binnenhalen als .rar, of gewoon hieronder kopieren :)

EDIT: de file op mijn server is geupdate, doet nu ook permutaties en zowel combinaties als permutaties met terugleggen :)

http://ruigekonijnen.nl/temp/mathhelper.rar

PHP:
<?php
/**
 * @Author: Erik Roelofs
 * @Created: 29 03 2009
 * @Email: 	Erik@Ruigekonijnen.nl
 * 
 * A Math Helper with a few functions to help with mathematical problems
 * Right now supports:
 * 	determinePrime() to figure out if a number is a prime ( not for HUGE numbers )
 *  factorize() to break a number into primes
 *  combinations() to determine the number of possible ways to take X objects from a collection of Y objects
 * 
 * Might be updated later.
 */

class mathhelper {
	
	/**
	 * In how many ways can we take $amount objects from $collection
	 * if we don't mind the order? 
	 *
	 * @param integer $collection
	 * @param ingeger $amount
	 * 
	 * @return integer (or float, if really big) $iAmountOfCombinations
	 */
	function combinations( $collection, $amount ) {
		// formal:
		// n! / ( k! ( n - k )! )
		
		// we're going to drop the largest set of the two, and remove all those numbers from $aCollectionNumbers
		// get the largest number
		$bottom = max ( $amount, $collection - $amount );
		
		// create the top range, which runs from (highest number dropped +1) to (collection) 
		// that is: numbers that exist exactly in both top and bottom of the calculation.
		$aTopNumbers = range( $bottom + 1, $collection );
		// create the bottom range, which runs from 1 to the collection minus the highest number dropped
		$aBottomNumbers = range ( 1, $collection - $bottom );
		
		// determine the factor list at the top of the division
		$aTop = array();
		foreach ( $aTopNumbers as $i ) {
			$aNewFactors = self::factorize( $i );
			foreach ( $aNewFactors as $factor => $amount_factors ) {
				if ( isset ( $aTop[ $factor ] ) ) {
					$aTop[ $factor ] += $amount_factors;
				}
				else {
					$aTop[ $factor ] = $amount_factors;
				}
			}
		}
				
		// determine the factor list at the bottom of the division
		$aBottom = array();
		foreach ( $aBottomNumbers as $i ) {
			$aNewFactors = self::factorize( $i );
			foreach ( $aNewFactors as $factor => $amount_factors ) {
				if ( isset ( $aBottom[ $factor ] ) ) {
					$aBottom[ $factor ] += $amount_factors;
				}
				else {
					$aBottom[ $factor ] = $amount_factors;
				}
			}
		}
		
		// now we simplify. first, clean as many factors that exist in both Collection and Amount as possible
		foreach ( $aBottom as $factor => $amount ) {
			if ( isset ( $aTop[ $factor ] ) ) {
				// at least some factors exist
				if ( $aTop[ $factor ] > $amount ) {
					// collection has more of them. remove a set from collection and all from amount
					$aTop[ $factor ] -= $amount;
					unset ( $aBottom[ $factor ] ); 
				}
				elseif ( $aTop[ $factor ] == $amount ) {
					// they have equal; unset both
					unset ( $aTop[ $factor ] );
					unset ( $aBottom[ $factor ] );					
				}
				else {
					// amount has more of them; unset from collection, lower amount
					unset ( $aTop[ $factor ] );
					$aBottom[ $factor ] -= $amount;
				}
			}
		}
		
		// calculate what's left of N!
		$topFaculty = 1;
		foreach ( $aTop as $factor => $amount ) {
			$topFaculty *= pow ( $factor, $amount );
		}

		// then calculate what's left of K!(N-K)!
		$bottomFaculty = 1;
		foreach ( $aBottom as $factor => $amount ) {
			$bottomFaculty *= pow ( $factor, $amount );
		}
		
		// and divide them.
		return $topFaculty / $bottomFaculty;
		
	}
	
	/**
	 * Crunch a number into all the primes that it's made up out of.
	 *
	 * @param positive integer $number
	 * @return array with key $factor and value $amount of times this factor is in the number
	 * 
	 * (Example: factorizing 12 would give
	 *  	array ( 
	 * 	 		2 => 2,
	 * 			3 => 1
	 *  	)
	 * 	because 12 is 2 x 2 x 3 )
	 */
	function factorize ( $number ) {
		
		if ( !is_numeric ( $number ) || $number < 1 ) {
			throw new Exception ( "Cannot factorize for non-positive number: " . $number );
		}
		
		// 1 is an exception
		if ( $number == 1 ) {
			return array( 1 => 1 );
		}
				
		$return = array();
		// divide by each prime as often as possible.
		foreach ( self::$primelist as $prime ) {
			while ( $number % $prime == 0 ) {
				// divisable.
				if ( isset ( $return[ $prime ] ) ) {
					$return[ $prime ]++;
				}
				else {
					$return[ $prime ] = 1;
				}
				$number /= $prime; 
			}
			// done?
			if ( $number == 1 ) {
				return $return;
			}
		}
		
		// not done... we need a bigger primes list.
		$new_primes = self::expandPrimeListUpTo( $number );
		
		// continue.
		foreach ( $new_primes as $prime ) {
			while ( $number % $prime == 0 ) {
				// divisable.
				if ( isset ( $return[ $prime ] ) ) {
					$return[ $prime ]++;
				}
				else {
					$return[ $prime ] = 1;
				}
				$number /= $prime; 
			}
			// done?
			if ( $number == 1 ) {
				return $return;
			}
		}		
		
		// unable to factorize? :/
		throw new Exception ( 'Was not able to factorize ' . $number . '; what the hell?' );
		
	}
	
	/**
	 * Determine if a number is a prime
	 * 
	 * @return 0 if the number is a prime, or the lowest divisor if it isn't.
	 */
	function determinePrime ( $number ) {
		
		// if this is negative or NaN, exception.
		if ( !is_numeric ( $number ) || $number < 1 ) {
			throw new Exception ( 'Not a positive integer: ' . $number );
		}
		
		// 1 is not a prime, and a special case.'
		if ( $number == 1 ) {
			return 0;
		}
		
		// if in our determined list; then it's fine.
		if ( isset ( self::$primelist[ $number ] ) ) {
			return 0;
		}
		// match against all known primes.
		foreach ( self::$primelist as $prime ) {
			// divisable; thus not a prime
			if ( $number % $prime == 0 ) {
				return $prime;
			}
		}
		// add more primes
		$new_primes = self::expandPrimeListUpTo ( (int) ceil ( sqrt ( $number ) ) );
		
		// now the list is full; check again if our original was a prime.
		foreach ( $new_primes as $prime ) {
			// divisable; thus not a prime
			if ( $number % $prime == 0 ) {
				return $prime;
			}
		}
		
		// it is a prime ;)
		return 0;
		
	}
	
	/**
	 * Will fill the internal list of primes up to $number
	 *
	 * @param integer $number
	 * @return array of primes added.
	 */
	private function expandPrimeListUpTo( $number ) {
		$return = array();
		// fill the list further		
		// hop in jumps of 2 (odds only; and primetop is always odd.)
		for ( $i = self::$primetop ; $i <= $number ; $i+=2 ) {
			// determine if this number is a prime.
			foreach ( self::$primelist as $prime ) {
				$is_prime = true;
				if ( $i % $prime == 0 ) {
					// it is not a prime; skip it.
					$is_prime = false;
					break;
				}
			}
			if ( $is_prime ) {
				// add this prime, continue.
				self::$primelist[ $i ] = $i;
				self::$primetop = $i;
				$return[] = $i;
			}
		}	
		return $return;
	}
	
	/**
	 * The class uses this array to speed up factorizing and prime number determinitation.
	 * You can put in more primes to make it go even faster for larger numbers.
	 * The downside is that it'll start taking up more memory too.
	 * $primetop is the highest prime in the array, keep it up to date if you add more primes or results may become unpredictable. 
	 * 
	 */
	static $primetop = 997;
	static $primelist = 
		array (
			2 => 2,
			3 => 3,
			5 => 5,
			7 => 7,
			11 => 11,
			13 => 13,
			17 => 17,
			19 => 19,
			23 => 23,
			29 => 29,
			31 => 31,
			37 => 37,
			41 => 41,
			43 => 43,
			47 => 47,
			53 => 53,
			59 => 59,
			61 => 61,
			67 => 67,
			71 => 71,
			73 => 73,
			79 => 79,
			83 => 83,
			89 => 89,
			97 => 97,
			101 => 101,
			103 => 103,
			107 => 107,
			109 => 109,
			113 => 113,
			127 => 127,
			131 => 131,
			137 => 137,
			139 => 139,
			149 => 149,
			151 => 151,
			157 => 157,
			163 => 163,
			167 => 167,
			173 => 173,
			179 => 179,
			181 => 181,
			191 => 191,
			193 => 193,
			197 => 197,
			199 => 199,
			211 => 211,
			223 => 223,
			227 => 227,
			229 => 229,
			233 => 233,
			239 => 239,
			241 => 241,
			251 => 251,
			257 => 257,
			263 => 263,
			269 => 269,
			271 => 271,
			277 => 277,
			281 => 281,
			283 => 283,
			293 => 293,
			307 => 307,
			311 => 311,
			313 => 313,
			317 => 317,
			331 => 331,
			337 => 337,
			347 => 347,
			349 => 349,
			353 => 353,
			359 => 359,
			367 => 367,
			373 => 373,
			379 => 379,
			383 => 383,
			389 => 389,
			397 => 397,
			401 => 401,
			409 => 409,
			419 => 419,
			421 => 421,
			431 => 431,
			433 => 433,
			439 => 439,
			443 => 443,
			449 => 449,
			457 => 457,
			461 => 461,
			463 => 463,
			467 => 467,
			479 => 479,
			487 => 487,
			491 => 491,
			499 => 499,
			503 => 503,
			509 => 509,
			521 => 521,
			523 => 523,
			541 => 541,
			547 => 547,
			557 => 557,
			563 => 563,
			569 => 569,
			571 => 571,
			577 => 577,
			587 => 587,
			593 => 593,
			599 => 599,
			601 => 601,
			607 => 607,
			613 => 613,
			617 => 617,
			619 => 619,
			631 => 631,
			641 => 641,
			643 => 643,
			647 => 647,
			653 => 653,
			659 => 659,
			661 => 661,
			673 => 673,
			677 => 677,
			683 => 683,
			691 => 691,
			701 => 701,
			709 => 709,
			719 => 719,
			727 => 727,
			733 => 733,
			739 => 739,
			743 => 743,
			751 => 751,
			757 => 757,
			761 => 761,
			769 => 769,
			773 => 773,
			787 => 787,
			797 => 797,
			809 => 809,
			811 => 811,
			821 => 821,
			823 => 823,
			827 => 827,
			829 => 829,
			839 => 839,
			853 => 853,
			857 => 857,
			859 => 859,
			863 => 863,
			877 => 877,
			881 => 881,
			883 => 883,
			887 => 887,
			907 => 907,
			911 => 911,
			919 => 919,
			929 => 929,
			937 => 937,
			941 => 941,
			947 => 947,
			953 => 953,
			967 => 967,
			971 => 971,
			977 => 977,
			983 => 983,
			991 => 991,
			997 => 997, 	
		);
	
}

?>
 
Laatst bewerkt:
Status
Niet open voor verdere reacties.
Steun Ons

Nieuwste berichten

Terug
Bovenaan Onderaan