I made this to multiply an unlimited size of integers together (meaning no decimals)..
This could be useful for those without the BCMath extension.
<?php
function Mul($Num1='0',$Num2='0') {
// check if they're both plain numbers
if(!preg_match("/^\d+$/",$Num1)||!preg_match("/^\d+$/",$Num2)) return(0);
// remove zeroes from beginning of numbers
for($i=0;$i<strlen($Num1);$i++) if(@$Num1{$i}!='0') {$Num1=substr($Num1,$i);break;}
for($i=0;$i<strlen($Num2);$i++) if(@$Num2{$i}!='0') {$Num2=substr($Num2,$i);break;}
// get both number lengths
$Len1=strlen($Num1);
$Len2=strlen($Num2);
// $Rema is for storing the calculated numbers and $Rema2 is for carrying the remainders
$Rema=$Rema2=array();
// we start by making a $Len1 by $Len2 table (array)
for($y=$i=0;$y<$Len1;$y++)
for($x=0;$x<$Len2;$x++)
// we use the classic lattice method for calculating the multiplication..
// this will multiply each number in $Num1 with each number in $Num2 and store it accordingly
@$Rema[$i++%$Len2].=sprintf('%02d',(int)$Num1{$y}*(int)$Num2{$x});
// cycle through each stored number
for($y=0;$y<$Len2;$y++)
for($x=0;$x<$Len1*2;$x++)
// add up the numbers in the diagonal fashion the lattice method uses
@$Rema2[Floor(($x-1)/2)+1+$y]+=(int)$Rema[$y]{$x};
// reverse the results around
$Rema2=array_reverse($Rema2);
// cycle through all the results again
for($i=0;$i<count($Rema2);$i++) {
// reverse this item, split, keep the first digit, spread the other digits down the array
$Rema3=str_split(strrev($Rema2[$i]));
for($o=0;$o<count($Rema3);$o++)
if($o==0) @$Rema2[$i+$o]=$Rema3[$o];
else @$Rema2[$i+$o]+=$Rema3[$o];
}
// implode $Rema2 so it's a string and reverse it, this is the result!
$Rema2=strrev(implode($Rema2));
// just to make sure, we delete the zeros from the beginning of the result and return
while(strlen($Rema2)>1&&$Rema2{0}=='0') $Rema2=substr($Rema2,1);
return($Rema2);
}
$A='5650175242508133742';
$B='2361030539975818701734615584174625';
printf(" Mul(%s,%s); // %s\r\n",$A,$B, Mul($A,$B));
printf("BCMul(%s,%s); // %s\r\n",$A,$B,BCMul($A,$B)); // build-in function
/*
This will print something similar to this..
Mul(5650175242508133742,2361030539975818701734615584174625);
BCMul(5650175242508133742,2361030539975818701734615584174625);
both of which should be followed by the answer:
13340236303776981390475700774516825287352418182696750
*/
?>
It was a fun experience making.. even though this took me longer than the BCAdd alternative I did..
Memory allocation might be an issue for rediculously larger numbers though.. if someone wants to benchmark the performance of my function; feel free.
Enjoy,
Nitrogen.
bcmul
(PHP 4, PHP 5)
bcmul — Multiplie deux nombres de grande taille
Description
string bcmul
( string $left_operand
, string $right_operand
[, int $scale
] )
Multiplie l'opérande left_operand par l'opérande right_operand .
Liste de paramètres
- left_operand
-
L'opérande de gauche, sous la forme d'une chaîne de caractères.
- right_operand
-
L'opérande de droite, sous la forme d'une chaîne de caractères.
- scale
-
Ce paramètre optionnel est utilisé pour définir le nombre de digits après la décimale à placer dans le résultat. Vous pouvez également définir la précision globale par défaut pour toutes les fonctions en utilisant la fonction bcscale().
Valeurs de retour
Retourne le résultat, sous la forme d'une chaîne de caractères.
Exemples
Exemple #1 Exemple avec bcmul()
<?php
echo bcmul('1.34747474747', '35', 3); // 47.161
echo bcmul('2', '4'); // 8
?>
bcmul
Nitrogen
09-Jul-2009 02:55
09-Jul-2009 02:55
ju(...)
02-Apr-2008 10:00
02-Apr-2008 10:00
Except that with xpheas method, you lose all the benefits of arbitrary precision as the * operator only works on int and float and those are restricted in length (See int ant float types for more information).
xpheas (at) gmail . com
14-Jun-2007 05:13
14-Jun-2007 05:13
if you have compiled php width "--disable-bcmath", you can use this:
<?php
function bcmul($_ro, $_lo, $_scale=0)
{
return round($_ro*$_lo, $_scale);
}
?>
