|
BCMath Arbitrary Precision Mathematics FunctionsFor arbitrary precision mathematics PHP offers the Binary Calculator which supports numbers of any size and precision, represented as strings. Since PHP 4.0.4, libbcmath is bundled with PHP. You don't need any external libraries for this extension.
These functions are only available if PHP was
configured with The windows version of PHP has built in support for this extension. You do not need to load any additional extension in order to use these functions.
The behaviour of these functions is affected by settings in Table 22. BC math configuration options
Here's a short explanation of the configuration directives.
Table of Contents
Code Examples / Notes » ref.bcmarcus
Oops, first posting contained wrong code... sorry. An amendment to the entry by pulstar at mail dot com - the digits() function can be made much faster (remove the line breaks from the big string, and make sure you don't miss any characters!): function digits2($base) { if($base < 64) { return substr('0123456789abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ-_', 0, $base); } else { return substr("\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xa\xb\xc\xd \xe\xf\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d \x1e\x1f\x20!\x22#\x24%&'()*+,-./0123456789:;<=> \x3f@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\] ^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85 \x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95 \x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5 \xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5 \xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5 \xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5 \xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5 \xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6 \xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", 0, $base); } } in my benchmarks, this is around 150x faster for 256 digits benjcarson
Note that bcmath doesn't seem to handle numbers in exponential notation (i.e. "1e4"), although PHP considers such a value a number. example: $exp1 = "1E5"; $exp2 = "2E4"; $ans1 = bcadd($exp1, $exp2, 3); $ans2 = $exp1 + exp2; echo("bcadd: $exp1 + $exp2 = $ans1"); echo("php: $exp1 + $exp2 = $ans2"); // Output: bcadd: 1E5 + 2E4 = 0.000 php: 1E5 + 2E4 = 120000 Just a gotcha if you're using passing PHP numbers into bcmath functions... stonehew ut gm a il det com
Like any other bc function, you can't trust the last couple of digits, but everything else seems to check out. If you want to use this for anything important, you may want to verify this against other sources of pi before use. This function calculates 100 decimal places of pi in 329 iterations -- not exactly fast (each iteration calls the factorial function, from below, twice), so I try to avoid calling it more than once. <? //arbitrary precision pi approximator //author tom boothby //free for any use function bcpi() { $r=2; $i=0; $or=0; while(bccomp($or,$r)) { $i++; $or=$r; $r = bcadd($r,bcdiv(bcmul(bcpow(bcfact($i),2), bcpow(2,$i+1)),bcfact(2*$i+1))); } return $r; } ?> benjcarson
In addition to my last note, here are a quick pair of functions to convert exponential notation values into bcmath-style number strings: // exp2int converts numbers in the // form "1.5e4" into strings function exp2int($exp) { list($mantissa, $exponent) = spliti("e", $exp); list($int, $dec) = split("\.", $mantissa); bcscale ($dec); return bcmul($mantissa, bcpow("10", $exponent)); } // float2exp converts floats into exponential notation function float2exp($num) { if (0 == $num) { return "0E1";} list($int, $dec) = split("\.", $num); // Extract sign if ($int[0] == "+" || $int[0] == "-") { $sign = substr($int, 0,1); $int = substr($int, 1); } if (strlen($int) <= 1) { // abs($num) is less than 1 $i=0; for ($i=0; $dec[$i]=='0' && $i < strlen($dec); $i++); $exp = -$i-1; $mantissa = substr($dec,$i,1).".".substr($dec,$i+1); } else { // abs($num) is greater than 1 $i=0; for ($i=0; $int[$i]=='0' && $i < strlen($int); $i++); $exp = strlen($int)-1 - $i; $mantissa = substr($int,$i,1).".".substr($int,$i+1).$dec; } return ($sign . $mantissa . "E" . $exp); } mgcclx
I wrote this function with many BCMath functions. It should be the fastest function in PHP to find the number pi into any precision, my test is it generate 2000 digits after the dot in 8 seconds. I don't think you need anything more than that. <?php //bcpi function with Gauss-Legendre algorithm //by Chao Xu (Mgccl) function bcpi($precision){ $limit = ceil(log($precision)/log(2))-1; bcscale($precision+6); $a = 1; $b = bcdiv(1,bcsqrt(2)); $t = 1/4; $p = 1; while($n < $limit){ $x = bcdiv(bcadd($a,$b),2); $y = bcsqrt(bcmul($a, $b)); $t = bcsub($t, bcmul($p,bcpow(bcsub($a,$x),2))); $a = $x; $b = $y; $p = bcmul(2,$p); ++$n; } return bcdiv(bcpow(bcadd($a, $b),2),bcmul(4,$t),$precision); } ?> robert
I spent some time looking for how to generate a large random number, in the end I've settled for reading directly from /dev/urandom I know this is a *nix only solution, but I figured that it might come in handy to someone else. The value $size is the size in bits, it could be simplified greatly if you want the size in bytes, but bits was more helpful to what I needed. <?php function bcrand($size) { $filename = "/dev/urandom"; $handle = fopen($filename, "r"); $bin_urand = fread($handle, ceil($size/8.0)); fclose($handle); $mask = (($size % 8 < 5) ? '0' : '') . dechex(bindec(str_repeat('1', $size % 8))) . str_repeat('FF', floor($size/8)); $binmask = pack("H*", $mask); $binrand = $binmask & $bin_urand; $hexnumber = unpack("H*", $binrand); $hexnumber = $hexnumber['']; $numlength = strlen($hexnumber); $decnumber = 0; for($x = 1; $x <= $numlength; $x++) { $place = $numlength - $x; $operand = hexdec(substr($hexnumber,$place,1)); $exponent = bcpow(16,$x-1); $decValue = bcmul($operand, $exponent); $decnumber = bcadd($decValue, $decnumber); } return $decnumber; } ?> stonehew et g m a i l dut com
I hacked these taylor expansions up to make diagrams for some physics homework. I don't think you'll be wanting to do any real science with PHP... but what the hell, why not? I plan to implement either a spigot algorithm or something similar to generate pi in the near future. <? // arbitrary precision sin and cosine functions // author tom boothby // free for any use function bcfact($n) { $r = $n--; while($n>1) $r=bcmul($r,$n--); return $r; } function bcsin($a) { $or= $a; $r = bcsub($a,bcdiv(bcpow($a,3),6)); $i = 2; while(bccomp($or,$r)) { $or=$r; switch($i%2) { case 0: $r = bcadd($r,bcdiv(bcpow($a,$i*2+1),bcfact($i*2+1))); break; default: $r = bcsub($r,bcdiv(bcpow($a,$i*2+1),bcfact($i*2+1))); break; } $i++; } return $r; } function bccos($a) { $or= $a; $r = bcsub(1,bcdiv(bcpow($a,2),2)); $i = 2; while(bccomp($or,$r)) { $or=$r; switch($i%2) { case 0: $r = bcadd($r,bcdiv(bcpow($a,$i*2),bcfact($i*2))); break; default: $r = bcsub($r,bcdiv(bcpow($a,$i*2),bcfact($i*2))); break; } $i++; } return $r; } ?> diabolos
Here's a function to compute the natural exponential function in arbitrary precision using the basic bcMath arithmetic operations. EXAMPLE: To compute the exponential function of 1.7 to 36 decimals: $y = bcExp("1.7", 36); The result: 4.331733759839529271053448625299468628 would be returned in variable $y NOTE: In practice, the last couple of digits may be inaccurate due to small rounding errors. If you require a specific degree of precision, always compute 3-4 decimals beyond the required precision. The program code for the natural exponential function is: ****************************************** Function bcExp($xArg, $NumDecimals) { $x = Trim($xArg); $PrevSum = $x - 1; $CurrTerm = 1; $CurrSum = bcAdd("1", $x, $NumDecimals); $n = 1; While (bcComp($CurrSum, $PrevSum, $NumDecimals)) { $PrevSum = $CurrSum; $CurrTerm = bcDiv(bcMul($CurrTerm, $x, $NumDecimals), $n + 1, $NumDecimals); $CurrSum = bcAdd($CurrSum, $CurrTerm, $NumDecimals); $n++; } Return $CurrSum; } udochen
Code below implements standard rounding on 5 or higer round up, else don't round. There wasn't a round function for the BC functions, so here is a simple one that works. Same args as round, except takes strings and returns a string for more BC operations. ---------------- function roundbc($x, $p) { $x = trim($x); $data = explode(".",$x); if(substr($data[1],$p,1) >= "5") { //generate the add string. $i=0; $addString = "5"; while($i < $p) { $addString = "0" . $addString; $i++; }//end while. $addString = "." . $addString; //now add the addString to the original fraction. $sum = bcadd($data[0] . "." . $data [1],$addString,$p+1); //explode the result. $sumData = explode(".",$sum); //now, return the correct precision on the rounded number. return $sumData[0] . "." . substr($sumData[1],0,$p); } else { //don't round the value and return the orignal to the desired //precision or less. return $data[0] . "." . substr($data[1],0,$p); }//end if/else. }//end roundbc. oliver
A simplier Version of the Script above: function dec2base($dec, $digits) { $value = ""; $base = strlen($digits); while($dec>$base-1) { $rest = $dec % $base; $dec = $dec / $base; $value = $digits[$rest].$value; } $value = $digits[intval($dec)].$value; return (string) $value; } function base2dec($value, $digits) { $value = strtoupper($value); $base = strlen($digits); $size = strlen($value); $dec = '0'; for ($loop = 0; $loop<$size; $loop++) { $element = strpos($digits,$value[$loop]); $power = pow($base,$size-$loop-1); $dec += $element * $power; } return (string) $dec; } $digits = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"; echo dec2base('1000', $digits); pulstar
A little comment for the simplified example above: you can do base converting without BCMath functions using only math operators, but you will not able to manage very large values or work with strings to compress or scramble data. If you have BCMath installed in your system it worth use it for this.
|
Change Language.NET Functions Apache-specific Functions Alternative PHP Cache Advanced PHP debugger Array Functions Aspell functions [deprecated] BBCode Functions BCMath Arbitrary Precision Mathematics Functions PHP bytecode Compiler Bzip2 Compression Functions Calendar Functions CCVS API Functions [deprecated] Class/Object Functions Classkit Functions ClibPDF Functions [deprecated] COM and .Net (Windows) Crack Functions Character Type Functions CURL Cybercash Payment Functions Credit Mutuel CyberMUT functions Cyrus IMAP administration Functions Date and Time Functions DB++ Functions Database (dbm-style) Abstraction Layer Functions dBase Functions DBM Functions [deprecated] dbx Functions Direct IO Functions Directory Functions DOM Functions DOM XML Functions enchant Functions Error Handling and Logging Functions Exif Functions Expect Functions File Alteration Monitor Functions Forms Data Format Functions Fileinfo Functions filePro Functions Filesystem Functions Filter Functions Firebird/InterBase Functions Firebird/Interbase Functions (PDO_FIREBIRD) FriBiDi Functions FrontBase Functions FTP Functions Function Handling Functions GeoIP Functions Gettext Functions GMP Functions gnupg Functions Net_Gopher Haru PDF Functions hash Functions HTTP Hyperwave Functions Hyperwave API Functions i18n Functions IBM Functions (PDO_IBM) IBM DB2 iconv Functions ID3 Functions IIS Administration Functions Image Functions Imagick Image Library IMAP Informix Functions Informix Functions (PDO_INFORMIX) Ingres II Functions IRC Gateway Functions PHP / Java Integration JSON Functions KADM5 LDAP Functions libxml Functions Lotus Notes Functions LZF Functions Mail Functions Mailparse Functions Mathematical Functions MaxDB PHP Extension MCAL Functions Mcrypt Encryption Functions MCVE (Monetra) Payment Functions Memcache Functions Mhash Functions Mimetype Functions Ming functions for Flash Miscellaneous Functions mnoGoSearch Functions Microsoft SQL Server Functions Microsoft SQL Server and Sybase Functions (PDO_DBLIB) Mohawk Software Session Handler Functions mSQL Functions Multibyte String Functions muscat Functions MySQL Functions MySQL Functions (PDO_MYSQL) MySQL Improved Extension Ncurses Terminal Screen Control Functions Network Functions Newt Functions NSAPI-specific Functions Object Aggregation/Composition Functions Object property and method call overloading Oracle Functions ODBC Functions (Unified) ODBC and DB2 Functions (PDO_ODBC) oggvorbis OpenAL Audio Bindings OpenSSL Functions Oracle Functions [deprecated] Oracle Functions (PDO_OCI) Output Control Functions Ovrimos SQL Functions Paradox File Access Parsekit Functions Process Control Functions Regular Expression Functions (Perl-Compatible) PDF Functions PDO Functions Phar archive stream and classes PHP Options&Information POSIX Functions Regular Expression Functions (POSIX Extended) PostgreSQL Functions PostgreSQL Functions (PDO_PGSQL) Printer Functions Program Execution Functions PostScript document creation Pspell Functions qtdom Functions Radius Rar Functions GNU Readline GNU Recode Functions RPM Header Reading Functions runkit Functions SAM - Simple Asynchronous Messaging Satellite CORBA client extension [deprecated] SCA Functions SDO Functions SDO XML Data Access Service Functions SDO Relational Data Access Service Functions Semaphore SESAM Database Functions PostgreSQL Session Save Handler Session Handling Functions Shared Memory Functions SimpleXML functions SNMP Functions SOAP Functions Socket Functions Standard PHP Library (SPL) Functions SQLite Functions SQLite Functions (PDO_SQLITE) Secure Shell2 Functions Statistics Functions Stream Functions String Functions Subversion Functions Shockwave Flash Functions Swish Functions Sybase Functions TCP Wrappers Functions Tidy Functions Tokenizer Functions Unicode Functions URL Functions Variable Handling Functions Verisign Payflow Pro Functions vpopmail Functions W32api Functions WDDX Functions win32ps Functions win32service Functions xattr Functions xdiff Functions XML Parser Functions XML-RPC Functions XMLReader functions XMLWriter Functions XSL functions XSLT Functions YAZ Functions YP/NIS Functions Zip File Functions Zlib Compression Functions |