PHP 8.4.2 Released!

bcmul

(PHP 4, PHP 5, PHP 7, PHP 8)

bcmulMultiplikation zweier Zahlen beliebiger Genauigkeit

Beschreibung

bcmul(string $num1, string $num2, ?int $scale = null): string

Multipliziert num1 mit num2.

Parameter-Liste

num1

Der linke Operand als Zeichenkette.

num2

Der rechte Operand als Zeichenkette.

scale
Dieser Parameter wird verwendet, um die Anzahl der Nachkommastellen im Ergebnis festzulegen. Falls null, wird die mit bcscale() definierte Standard-Genauigkeit verwendet oder auf den Wert der INI-Direktive bcmath.scale zurückgegriffen.

Rückgabewerte

Gibt das Ergebnis als Zeichenkette zurück.

Fehler/Exceptions

Diese Funktion löst in den folgenden Fällen einen ValueError aus:

  • num1 oder num2 ist keine wohlgeformte numerische BCMath-Zeichenkette.
  • scale liegt außerhalb des gültigen Bereichs.

Changelog

Version Beschreibung
8.0.0 scale ist jetzt nullbar.
7.3.0 bcmul() liefert nun Zahlen mit den angeforderten Nachkommastellen zurück. Zuvor haben die zurückgelieferten Zahlen möglicherweise abschließende Dezimalnullen ausgelassen.

Beispiele

Beispiel #1 bcmul()-Beispiel

<?php
echo bcmul('1.34747474747', '35', 3); // 47.161
echo bcmul('2', '4'); // 8
?>

Anmerkungen

Hinweis:

Vor PHP 7.3.0 kann bcmul() ein Ergebnis mit weniger Nachkommastellen zurückgeben, als der Parameter scale angibt. Dies geschieht nur, wenn das Ergebnis nicht die gesamte durch scale erlaubte Genauigkeit erfordert. Zum Beispiel:

Beispiel #2 bcmul()-Nachkommastellen-Beispiel

<?php
echo bcmul('5', '2', 2); // gibt "10" aus, nicht "10.00"
?>

Siehe auch

  • bcdiv() - Division zweier Zahlen beliebiger Genauigkeit

add a note

User Contributed Notes 4 notes

up
10
Nitrogen
15 years ago
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.
up
7
mgkirs
7 years ago
$float = 0.31234144143341;
$float1 = 0.00000000000000000000000000000005;
echo $float, "\n";
//0.31234144143341
echo $float1, "\n";
//5.0E-32
echo $float*$float1, "\n";
//1.5617072071671E-32

<?php
/*bcmul read float as string*/
echo bcmul($float, $float1, 32),"\n";
//0
echo bcmul($float, sprint('%.32f',$float1), 32);
//0.000000000000000000000000000000015617072071671;
?>
up
4
admin at spamhere dot sinfocol dot org
13 years ago
Well, I have a little problem implementing Blake Hash in my server because it is not a x64 server machine. I made a little function that use the powerfull of BC library to do the bitwise operation Shift.

<?php
echo 'Left Shift test<br />';
bprint('1', decbin(1));
bprint('1 << 32 (Fail)', decbin(1 << 32)); //Fail, operation not succesfull in 32-bit machine
bprint('shiftleft(1, 32) (Success)', dec2bin(shiftleft('1', '32'))); //decbin fails, so we use personalized function, success

echo '<br />';
echo
'Right Shift test<br />';
bprint('9223372036854775808', dec2bin('9223372036854775808'));
bprint('9223372036854775808 >> 63 (Fail)', decbin(9223372036854775808 >> 63));
bprint('rightshift(9223372036854775808, 63) (Success)', decbin(rightshift('9223372036854775808', '63')));

function
shiftleft($num, $bits) {
return
bcmul($num, bcpow('2', $bits));
}

function
rightshift($num, $bits) {
return
bcdiv($num, bcpow('2', $bits));
}

function
bprint($title, $content) {
echo
$title . '<br />' . str_pad($content, 64, '0', STR_PAD_LEFT) . '<br />' . PHP_EOL;
}

//http://www.php.net/manual/en/function.decbin.php#99533
function dec2bin($dec) {
// Better function for dec to bin. Support much bigger values, but doesn’t support signs
for ($b = '', $r = $dec; $r >1;) {
$n = floor($r / 2);
$b = ($r - $n * 2) . $b;
$r = $n; // $r%2 is inaccurate when using bigger values (like 11.435.168.214)!
}
return (
$r % 2) . $b;
}
?>
up
0
gar37bic at gmail dot com
12 years ago
When using printf to print the results of bcmath operations, use string format, i.e. '%s', not numeric formats such as '%d' or '%f'. For example, the output of factorial (23) will be incorrect if using %d or %f:

Result using %f:
factorial (22) = 1124000727777607680000 (correct)
factorial (23) = 25852016738884978212864 (incorrect)

Result using %s:
factorial (22) = 1124000727777607680000
factorial (23) = 25852016738884976640000

Using echo, this is not a problem - PHP will output the bcmath string type correctly.
To Top