PHP: BCMath funkce pro v�po�ty s libovolnou p�esnost� - Manual
PHP  
downloads | documentation | faq | getting help | mailing lists | | php.net sites | links | my php.net 
search for in the  
<aspell_suggestbcadd>
view the version of this page
Last updated: Thu, 15 Jul 2004

IV. BCMath funkce pro v�po�ty s libovolnou p�esnost�

�vod

Pro pr�ci s ��sly libovoln� p�esnosti PHP nab�z� Binary Calculator, kter� podporuje ��sla libovoln� velk� a s libovolnou p�esnost�, kter� jsou reprezentov�na jako �et�zce.

Po�adavky

Od PHP 4.0.4 je knihovna libbcmath dod�v�na s PHP. Pro toto roz���en� tedy nepot�ebujete ��dn� extern� knihovny.

Instalace

Tyto funkce jsou v PHP 4 dostupn� pouze pokud bylo PHP zkonfigurov�no s volbou --enable-bcmath. V PHP 3 jsou dostupn�, pokud nebylo zkonfigurov�no s volbou --disable-bcmath.

Verze PHP pro Windows m� vestav�nou podporu pro toto roz���en�. K pou�it� t�chto funkc� nen� t�eba na��tat ��dn� dal�� roz���en�.

Konfigurace b�hu

Chov�n� t�chto funkc� je ovlivn�no nastaven�m parametr� v php.ini.

Tabulka 1. BC math configuration options

NameDefaultChangeable
bcmath.scale0PHP_INI_ALL
For further details and definition of the PHP_INI_* constants see ini_set().

Zde je stru�n� vysv�tlen� konfigura�n�ch direktiv.

bcmath.scale integer

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

Typy prost�edk�

Toto roz���en� nem� definov�n ��dn� typ prost�edku (resource).

P�eddefinovan� konstanty

Toto roz���en� nem� definov�ny ��dn� konstanty.

Obsah
bcadd -- Se��st dv� ��sla s libovolnou p�esnost�
bccomp -- Porovnat dv� ��sla s libovolnou p�esnost�
bcdiv -- D�lit dv� ��sla s libovolnou p�esnost�
bcmod -- Z�skat modulus ��sla s libovolnou p�esnost�
bcmul -- Vyn�sobit dv� ��sla s libovolnou p�esnost�
bcpow --  Umocnit jedno ��slo na jin� s libovolnou p�esnost�
bcpowmod --  Raise an arbitrary precision number to another, reduced by a specified modulus.
bcscale -- Nastavit v�choz� �k�lu pro v�echny bc math funkce
bcsqrt --  Z�skat druhou odmocninu ��sla s libovolnou p�esnost�
bcsub --  Ode��st jedno ��slo od druh�ho s libovolnou p�esnost�


add a note add a note User Contributed Notes
BCMath funkce pro v�po�ty s libovolnou p�esnost�
Diabolos at GMail dot com
28-Oct-2004 06: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 04: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 12: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 06: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 02: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 03: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 12: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
07-Jul-2002 11: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...

<aspell_suggestbcadd>
 Last updated: Thu, 15 Jul 2004
show source | credits | sitemap | contact | advertising | mirror sites 
Copyright © 2001-2004 The PHP Group
All rights reserved.
This unofficial mirror is operated at: /
Last updated: Sun Nov 14 23:09:54 2004 Local time zone must be set--see zic manual page