This version of the page http://ua.php.net/manual/tw/ref.bc.php (0.0.0.0) stored by archive.org.ua. It represents a snapshot of the page as of 2008-08-02. The original page over time could change.
PHP: BC math - Manual
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

  • PHP Manual
  • 函式參考
  • .NET
  • Apache
  • APC
  • APD
  • Arrays
  • Aspell
  • BBCode
  • BC math
  • bcompiler
  • Bzip2
  • Calendar
  • CCVS
  • Classes/Objects
  • Classkit
  • ClibPDF
  • COM
  • Crack
  • ctype
  • CURL
  • Cybercash
  • CyberMUT
  • Cyrus IMAP
  • Date/Time
  • DB++
  • dba
  • dBase
  • DBM
  • dbx
  • Direct IO
  • Directories
  • DOM
  • DOM XML
  • enchant
  • Errors and Logging
  • Exif
  • Expect
  • fam
  • FDF
  • Fileinfo
  • filePro
  • Filesystem
  • Filter
  • Firebird/InterBase
  • Firebird/Interbase (PDO)
  • FriBiDi
  • FrontBase
  • FTP
  • Function handling
  • GeoIP
  • gettext
  • GMP
  • gnupg
  • gopher
  • haru
  • hash
  • http
  • Hyperwave
  • Hyperwave API
  • i18n
  • IBM (PDO)
  • ibm_ db2
  • iconv
  • id3
  • IIS Functions
  • Image
  • Imagick Image Library
  • IMAP
  • Informix
  • Informix (PDO)
  • Ingres II
  • IRC Gateway
  • Java
  • JSON
  • kadm5
  • LDAP
  • libxml
  • Lotus Notes
  • LZF
  • Mail
  • Mailparse
  • Math
  • MaxDB
  • MCAL
  • mcrypt
  • MCVE
  • Memcache
  • mhash
  • Mimetype
  • Ming (flash)
  • Misc.
  • mnoGoSearch
  • MS SQL Server
  • MS SQL Server (PDO)
  • Msession
  • mSQL
  • Multibyte String
  • muscat
  • MySQL
  • MySQL (PDO)
  • mysqli
  • Ncurses
  • Network
  • Newt
  • NSAPI
  • Object Aggregation
  • Object overloading
  • OCI8
  • ODBC
  • ODBC and DB2 (PDO)
  • OGG/Vorbis
  • openal
  • OpenSSL
  • Oracle
  • Oracle (PDO)
  • Output Control
  • OvrimosSQL
  • Paradox
  • Parsekit
  • PCNTL
  • PCRE
  • PDF
  • PDO
  • phar
  • PHP Options/Info
  • POSIX
  • POSIX Regex
  • PostgreSQL
  • PostgreSQL (PDO)
  • Printer
  • Program Execution
  • PS
  • Pspell
  • qtdom
  • radius
  • Rar
  • Readline
  • Recode
  • RPMReader
  • runkit
  • SAM
  • Satellite
  • SCA
  • SDO
  • SDO DAS XML
  • SDO-DAS-Relational
  • Semaphore
  • SESAM
  • Session PgSQL
  • Sessions
  • shmop
  • SimpleXML
  • SNMP
  • SOAP
  • Sockets
  • spl
  • SQLite
  • SQLite (PDO)
  • ssh2
  • Statistics
  • Streams
  • Strings
  • SVN
  • SWF
  • swish
  • Sybase
  • TCP Wrappers
  • tidy
  • Tokenizer
  • Unicode
  • URLs
  • Variables handling
  • Verisign Payflow Pro
  • vpopmail
  • W32api
  • WDDX
  • win32ps
  • win32service
  • xattr
  • xdiff
  • XML
  • XML-RPC
  • XMLReader
  • XMLWriter
  • XSL
  • XSLT
  • YAZ
  • YP/NIS
  • Zip
  • Zlib
bcadd bbcode_set_flags
Last updated: Sun, 25 Nov 2007

view this page in

BCMath Arbitrary Precision Mathematics Functions

簡介

For 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 --enable-bcmath. In PHP 3, these functions are only available if PHP was not configured with --disable-bcmath.

PHP 的 Windows 版本已經內置該擴充功能的支援。無需載入任何附加擴充功能即可使用這些函式。

執行時期設定

這些函式的行為受 php.ini 的影響。

BC math configuration options
Name Default Changeable Changelog
bcmath.scale "0" PHP_INI_ALL  
有關 PHP_INI_* 常數進一步的細節與定義參見php.ini directives。

以下是設定選項的簡要解釋。

bcmath.scale integer

Number of decimal digits for all bcmath functions. See also bcscale().

資源類型

本擴充功能未定義任何資源類型。

預設常數

本擴充功能未定義任何常數。

Table of Contents

  • bcadd — Add two arbitrary precision numbers
  • bccomp — Compare two arbitrary precision numbers
  • bcdiv — Divide two arbitrary precision numbers
  • bcmod — Get modulus of an arbitrary precision number
  • bcmul — Multiply two arbitrary precision number
  • bcpow — Raise an arbitrary precision number to another
  • bcpowmod — Raise an arbitrary precision number to another, reduced by a specified modulus
  • bcscale — Set default scale parameter for all bc math functions
  • bcsqrt — Get the square root of an arbitrary precision number
  • bcsub — Subtract one arbitrary precision number from another


bcadd bbcode_set_flags
Last updated: Sun, 25 Nov 2007
 
add a note User Contributed Notes
BC math
vinni10 at gmx dot net
28-Jul-2008 04:48
Here is a better bcrand() version.
It uses the standart mt_rand() funktion and should work on other systems then unix ;-)

<?php
/**
 * BCrand - Generates very big random numbers.
 * string bcrand([mixed $min], mixed $max);
 */

function bcrand($min, $max=false)
{
    if(!
$max)
    {
       
$max = $min;
       
$min = 0;
    }
   
   
    return
bcadd(
               
bcmul(
                   
bcdiv(
                       
mt_rand(0, mt_getrandmax()),
                       
mt_getrandmax(),
                       
                       
strlen($max)
                    ),
                   
bcsub(
                       
bcadd($max,1),
                       
$min
                   
)
               
                ),
               
$min
           
);
}

echo
bcrand("0", "9999999999999999999999999999999999999999999999999999999999");

?>

Hope i could help someone :-)
Bouke Haarsma
29-Mar-2008 01:40
Please be aware not to use/have spaces in your strings. It took me a while to find the error in some advanced calculations!

<?php
echo bcadd("1", "2"); // 3
echo bcadd("1", "2 "); // 1
echo bcadd("1", " 2"); // 1
?>
bebaWork at gmail dot com
05-Dec-2007 04:11
For install on Feora Core:

> yum install php-bcmath
> /etc/init.d/httpd restart
udochen at gmail dot com
27-Feb-2007 09:48
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.
mgcclx at gmail dot com
30-Jan-2007 04:52
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);
}
?>
marcus at synchromedia dot co dot uk
09-Aug-2006 07:17
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
stonehew ut gm a il det com
25-Nov-2004 07:31
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;
}

?>
stonehew et g m a i l dut com
24-Nov-2004 09:20
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 at GMail dot com
28-Oct-2004 09:42
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;
}
robert at scabserver dot com
03-Jun-2004 07:58
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;
}
?>
pulstar at mail dot com
16-Apr-2003 03:12
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.
oliver at summertime dot net
01-Mar-2003 08:12
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 at mail dot com
20-Sep-2002 05:23
A found a little fix to do in my base2dec() function:
The line "if($base<37) $value=strtolower($value);" should be removed if you want to specify another digits for your base conversions. Change it this way:

if(!$digits) {
$digits=digits($base);
if($base<37) {
$value=strtolower($value);
}
}

Another example using these functions is to generate a key for a session, to name temporary files or something else:

srand((double) microtime()*1000000);
$id=uniqid(rand(10,999));
$mykey=dec2base(base2dec($id,16),64);

$mykey is a base64 value, which is a good key for passing thru an URL and also is shorter than a MD5 string (it will be allways 11 chars long). If you need something more secure, just scramble the 64 digits in the digits() function.

Well, I hope you enjoy it.

Regards,
Edemilson Lima
pulstar at mail dot com
20-Sep-2002 06:27
A good use for BCMath functions:
The functions below can convert a number in any base (from 2 to 256) to its decimal value and vice-versa.

// convert a decimal value to any other base value
function dec2base($dec,$base,$digits=FALSE) {
    if($base<2 or $base>256) die("Invalid Base: ".$base);
    bcscale(0);
    $value="";
    if(!$digits) $digits=digits($base);
    while($dec>$base-1) {
        $rest=bcmod($dec,$base);
        $dec=bcdiv($dec,$base);
        $value=$digits[$rest].$value;
    }
    $value=$digits[intval($dec)].$value;
    return (string) $value;
}

// convert another base value to its decimal value
function base2dec($value,$base,$digits=FALSE) {
    if($base<2 or $base>256) die("Invalid Base: ".$base);
    bcscale(0);
    if($base<37) $value=strtolower($value);
    if(!$digits) $digits=digits($base);
    $size=strlen($value);
    $dec="0";
    for($loop=0;$loop<$size;$loop++) {
        $element=strpos($digits,$value[$loop]);
        $power=bcpow($base,$size-$loop-1);
        $dec=bcadd($dec,bcmul($element,$power));
    }
    return (string) $dec;
}

function digits($base) {
    if($base>64) {
        $digits="";
        for($loop=0;$loop<256;$loop++) {
            $digits.=chr($loop);
        }
    } else {
        $digits ="0123456789abcdefghijklmnopqrstuvwxyz";
        $digits.="ABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
    }
    $digits=substr($digits,0,$base);
    return (string) $digits;
}

The purpose of digits() function above is to supply the characters that will be used as digits for the base you want. NOTE: You can use any characters for that when you convert to another base, but when you convert again to the decimal base, you need to use the same characters or you will get another unexpected result.
benjcarson at digitaljunkies dot ca
08-Jul-2002 03:00
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);
}
benjcarson at digitaljunkies ca
08-Jul-2002 02:17
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...
add a note

bcadd bbcode_set_flags
Last updated: Sun, 25 Nov 2007
 
 
show source | credits | sitemap | contact | advertising | mirror sites