bcmul
(PHP 4, PHP 5, PHP 7, PHP 8)
bcmul — 2つの任意精度数値の乗算を行う
パラメータ
num1
-
左オペランドを表す文字列。
num2
-
右オペランドを表す文字列。
scale
-
This parameter is used to set the number of digits after the decimal place in the result.
If
null
, it will default to the default scale set with bcscale(), or fallback to the value of thebcmath.scale
INI directive.
戻り値
結果を文字列で返します。
エラー / 例外
This function throws a ValueError in the following cases:
-
num1
ornum2
is not a well-formed BCMath numeric string. -
scale
is outside the valid range.
変更履歴
バージョン | 説明 |
---|---|
8.0.0 |
scale は、nullable になりました。
|
7.3.0 | bcmul() 関数が、指定されたスケールの数値を返すようになりました。 これより前のバージョンでは、 返される数値の末尾が 0埋め されることなく、省略される可能性がありました。 |
例
例1 bcmul() の例
<?php
echo bcmul('1.34747474747', '35', 3); // 47.161
echo bcmul('2', '4'); // 8
?>
注意
注意:
PHP 7.3.0 より前のバージョンでは、 bcmul() は
scale
引数で指定したものより少ない桁数を返す可能性がありました。 これはscale
で許された精度が不要な場合にだけ起きていました。 たとえば、以下のような場合です:例2 bcmul() で scale を指定する例
<?php
echo bcmul('5', '2', 2); // prints "10", not "10.00"
?>
+add a note
User Contributed Notes 4 notes
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.
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;
?>
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;
}
?>
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.
↑ and ↓ to navigate •
Enter to select •
Esc to close
Press Enter without
selection to search using Google